wpinc.ru wordpress WP Inc

Как использовать фильтр pre_get_posts для исключения типов записей из главного запроса WordPress

Диагностика проблемы: почему нужно исключать типы записей из главного запроса

При создании пользовательских типов записей (custom post types) в WordPress часто возникает необходимость исключить их из главного запроса на страницах блога или архивах. Если этого не сделать, на главной странице или в ленте новостей могут отображаться записи, которые не должны там показываться, например, портфолио, товары WooCommerce или отзывы.

Проверить, включены ли нежелательные типы записей в главный запрос, можно с помощью простого вывода типов в цикле. Для этого временно добавьте следующий код в файл functions.php вашей темы или в плагин:

add_action('pre_get_posts', function($query) {
    if ($query->is_main_query() && !is_admin()) {
        error_log(print_r($query->query_vars, true));
    }
});

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

Пошаговое решение: как исключить типы записей с помощью pre_get_posts

1. Определите, где именно хотите исключить типы записей

Чаще всего исключение нужно для главной страницы блога (is_home()) или для архивов определённого типа (is_archive()), а также для главного запроса (is_main_query()) — чтобы не ломать админку или дополнительные WP_Query.

2. Добавьте фильтр в functions.php или плагин

add_action('pre_get_posts', function($query) {
    if (is_admin() || !$query->is_main_query()) {
        return;
    }

    if ($query->is_home() || $query->is_archive()) {
        // Получаем текущий параметр post_type
        $post_types = $query->get('post_type');

        if (empty($post_types)) {
            // По умолчанию это 'post'
            $post_types = ['post'];
        } elseif (!is_array($post_types)) {
            $post_types = [$post_types];
        }

        // Типы записей, которые нужно исключить
        $excluded = ['portfolio', 'product', 'testimonial'];

        // Убираем исключаемые типы
        $post_types = array_diff($post_types, $excluded);

        // Если после исключения пусто, ставим 'post' по умолчанию
        if (empty($post_types)) {
            $post_types = ['post'];
        }

        // Обновляем параметр запроса
        $query->set('post_type', $post_types);
    }
});

3. Проверьте работу фильтра

Очистите кэш сайта и браузера, затем откройте главную страницу блога и архивы. Записи типов, указанных в массиве $excluded, не должны отображаться.

Для дополнительной проверки можно временно добавить вывод в лог текущего параметра post_type прямо в фильтре:

error_log('Post types in query: ' . print_r($query->get('post_type'), true));

Проверьте логи сервера или используйте плагин Debug Bar.

Частые ошибки и как их исправить

  • Фильтр срабатывает в админке — забудьте добавить проверку is_admin() и is_main_query(). Это приводит к нарушению функционала в админке.
  • Параметр post_type установлен в строку, а не массив — нужно всегда приводить к массиву перед исключением, иначе array_diff не сработает корректно.
  • После исключения массив пустой — WordPress может не показать записи. В этом случае обязательно установите хотя бы один тип по умолчанию, например post.
  • Забыли очистить кэш — результаты не обновятся до очистки кеша плагинов и браузера.

Проверка результата после внедрения

Чтобы убедиться, что фильтр работает:

  1. Откройте главную страницу блога и убедитесь, что записи из исключённых типов не показываются.
  2. Перейдите на архивные страницы, если применимо, и проверьте аналогично.
  3. Включите вывод параметра post_type в лог и убедитесь, что исключённые типы отсутствуют в запросе.
  4. Проверьте, что в админке все записи доступны и ничего не сломалось.

Практические советы по производительности и безопасности

  • Добавляйте фильтр только для главного запроса, чтобы не влиять на пользовательские WP_Query и админку.
  • Избегайте жёстко прописанных типов записей — лучше вынести список исключаемых типов в отдельную опцию или константу.
  • Если исключаете типы записей WooCommerce (product), убедитесь, что это не нарушит работу связанных функций и виджетов.

Сравнение вариантов решения

МетодПлюсыМинусы
pre_get_postsГибкий контроль, работает на уровне запроса, не требует сторонних плагиновНужно аккуратно фильтровать, чтобы не сломать админку или другие WP_Query
Использование плагинов фильтрации контентаИнтуитивный интерфейс, меньше кодаНагрузка на сайт, меньше гибкости, не всегда подходит для точечного исключения
Редактирование шаблонов темы (условные теги)Простота для простых случаевНебольшая гибкость, дублирование кода, не масштабируемо
×
WordPress
дай сайту суперсилу!

Скидки на топовые темы и плагины

Активировать суперсилу ⋙