WP API: Получить посты, исключая те, которые имеют имя тега или категории

Вопрос или проблема

Я знаю из этого поста, что я могу получить посты по тегу имя, просто указав параметр запроса filter[tag]. Точно так же с filter[category_name].

Есть ли способ получить посты, которые не находятся в списке тегов или категорий, чтобы исключить посты? Я предпочел бы сделать это по имени, иначе мне придется сделать еще один запрос, чтобы получить ID категории, что только замедлит общее время отклика в моем приложении.

Таким образом, один из способов сделать это заключается в создании фильтра для проверки на наличие пользовательского параметра строки запроса, который представляет собой имя или имена тегов.

Я добавил функцию, подобную этой, в свою тему. Она модифицирует глобальный объект WP_Query перед тем, как будет выполнен запрос на получение постов через REST API.

add_filter('pre_get_posts', function ($query) {
        // Я не мог считывать из query_vars по какой-то причине, поэтому использую глобальный $_GET
        $exclude_tag_name = isset($_GET['exclude_tag_name']);

        if (!$exclude_tag_name) {
            return; // Ничего не нужно делать
        }

        // Белый список для безопасности
        // Добавляйте в этот список по мере необходимости
        $whitelist = ['SomeExcludedTagNameHere'];

        $tag_name = $exclude_tag_name;

        // Дополнительная логика для обработки нескольких имен, например, разбиение

        // Проверяем, есть ли имя тега в белом списке (с строгой проверкой типов)
        // Для безопасности вы также можете использовать REGEX для очистки
        // или одну из встроенных функций WP для очистки.
        if (!in_array($tag_name, $whitelist, true)) {
            return; // Ничего не нужно делать
        }

        // Получаем все теги, содержащие это имя (без учета регистра)
        // Или просто используйте тег напрямую, если это не важно.
        $tags = get_tags([
            'search' => $tag_name
        ]);

        $tag_ids = [];
        foreach ($tags as $tag) {
            $tag_ids[] = $tag->term_id;
        }

        // Исключаем эти ID категорий из запроса
        if (!empty($tag_ids)) {
            // Модифицируем объект запроса, который был передан по ссылке
            // Эта функция использует ID тега, а не названия!
            $query->set('tag__not_in', $tag_ids);
        }
});

Похожий код можно использовать, чтобы включить только посты, которые были отмечены определенным тегом.

Вы можете попробовать использовать действие rest_post_query, чтобы добавить фильтры исключения для категорий и тегов. Попробуйте что-то вроде ниже.

Это добавляет ['filter']['exclude_categories'] и ['filter']['exclude_tags'] как опции для использования в WP REST API. Каждый фильтр принимает несколько категорий/тегов, разделенных запятой.

add_action( 'rest_post_query', 'your_exclude_query', 10, 2 );
function your_exclude_query( $args, $request ) {

    // Исключающий запрос
    if ( isset($request['filter']['exclude_categories']) || isset($request['filter']['exclude_tags']) ) {

        // Если установлен фильтр исключения категорий
        if ( isset($request['filter']['exclude_categories']) ) {
            $categories = explode( ',', $request['filter']['exclude_categories'] ); // ЗАМИТКА: предполагает, что таксономии разделены запятыми
            array_push( $pre_tax_query, array(
                'taxonomy' => 'category',
                'field' => 'name',
                'terms' => array( $categories ),
                'operator' => 'NOT IN'
            ));
        }

        // Если установлен фильтр исключения тегов
        if ( isset($request['filter']['exclude_tags']) ) {
            $tags = explode( ',', $request['filter']['exclude_tags'] );  // ЗАМИТКА: предполагает, что таксономии разделены запятыми
            array_push( $pre_tax_query, array(
                'taxonomy' => 'post_tag',
                'field' => 'name',
                'terms' => array( $tags ),
                'operator' => 'NOT IN'
            ));
        }

        $tax_query = array(
            'relation' => 'AND',
            $pre_tax_query
        );

        $args[ 'tax_query' ] = $tax_query;

    }

    return $args;

} // конец your_exclude_query

Это старый вопрос, но я думаю, что на данный момент решение существует.

Мы можем использовать tags_exclude=<tag-id> для исключения конкретных тегов.

Ответ или решение

Работа с WP API: Получение постов без определенных тегов или категорий

Чтобы получить посты в WordPress, исключая определенные теги или категории, вы можете использовать REST API с вспомогательными функциями, которые позволят добавлять фильтры на основе имени тегов или категорий. Данная задача может показаться непростой, особенно если вы хотите избежать лишних запросов для получения ID тегов или категорий. Рассмотрим детальный подход, позволяющий оптимизировать этот процесс, не теряя в производительности.

Подход 1: Фильтрация с использованием хука pre_get_posts

Один из самых простых способов — это использование хука pre_get_posts, который позволяет модифицировать запрос перед его выполнением. В частности, вы можете создать фильтр, который будет обрабатывать параметр exclude_tag_name и исключать посты по именам тегов.

Вот пример, как это можно сделать:

add_filter('pre_get_posts', function ($query) {
    // Проверка на наличие пользовательского параметра
    $exclude_tag_name = isset($_GET['exclude_tag_name']) ? $_GET['exclude_tag_name'] : null;

    if (!$exclude_tag_name) {
        return; // Выход, если параметр не установлен
    }

    // Белый список тегов для безопасности
    $whitelist = ['SomeExcludedTagNameHere']; 

    // Проверка на наличие тега в белом списке
    if (!in_array($exclude_tag_name, $whitelist, true)) {
        return; // Выход, если тег не в белом списке
    }

    // Получение ID тегов по имени
    $tags = get_tags(['search' => $exclude_tag_name]);
    $tag_ids = wp_list_pluck($tags, 'term_id');

    // Исключение тегов из запроса
    if (!empty($tag_ids)) {
        $query->set('tag__not_in', $tag_ids);
    }
});

Подход 2: Использование хука rest_post_query

Если вам нужно более гибкое решение, вы можете использовать хук rest_post_query, чтобы добавлять параметры фильтрации при запросах через WP REST API. Это позволит передавать параметры exclude_categories и exclude_tags в запрос и обрабатывать их аналогичным образом.

Пример реализации:

add_action('rest_post_query', 'your_exclude_query', 10, 2);
function your_exclude_query($args, $request) {
    // Проверка на наличие параметров исключения
    if (isset($request['filter']['exclude_categories']) || isset($request['filter']['exclude_tags'])) {
        $pre_tax_query = [];

        // Обработка исключаемых категорий
        if (isset($request['filter']['exclude_categories'])) {
            $categories = explode(',', $request['filter']['exclude_categories']);
            $pre_tax_query[] = [
                'taxonomy' => 'category',
                'field'    => 'name',
                'terms'    => $categories,
                'operator' => 'NOT IN'
            ];
        }

        // Обработка исключаемых тегов
        if (isset($request['filter']['exclude_tags'])) {
            $tags = explode(',', $request['filter']['exclude_tags']);
            $pre_tax_query[] = [
                'taxonomy' => 'post_tag',
                'field'    => 'name',
                'terms'    => $tags,
                'operator' => 'NOT IN'
            ];
        }

        // Построение окончательного tax_query
        if (!empty($pre_tax_query)) {
            $args['tax_query'] = $pre_tax_query;
        }
    }

    return $args;
}

Заключение

Используя данные методы, вы можете эффективно исключать посты, основанные на тегах или категориях. Это не только улучшает производительность вашего приложения, но и упрощает код, сводя к минимуму количество запросов к базе данных.

Не забывайте следить за безопасностью при обработке пользовательских данных. Используйте только проверенные имена для тегов и категорий, чтобы избежать возможных атак через SQL-инъекции.

Оцените материал
Добавить комментарий

Капча загружается...