Что такое фильтр pre_get_posts и для чего он нужен
Фильтр pre_get_posts позволяет изменить основной запрос WordPress перед его выполнением. Это мощный инструмент для тонкой настройки выборки записей без создания новых WP_Query. Чаще всего его используют, чтобы изменить поведение главной страницы, архивов, поисковых результатов, страниц категории или кастомных таксономий.
Диагностика задачи: когда и почему стоит использовать pre_get_posts
Частая ситуация — нужно исключить из каталога определённые категории, добавить дополнительные условия фильтрации или изменить порядок сортировки без дублирования кода и создания нового запроса. Если вы используете WP_Query в шаблоне, это усложняет поддержку и может привести к проблемам с пагинацией.
Чтобы понять, что фильтр pre_get_posts вам подходит:
- Проверьте, не работает ли уже основной запрос (например, на главной или архивной странице)
- Убедитесь, что результат нужно изменить глобально, а не локально в одном месте
- Если пагинация ломается после кастомных WP_Query — это признак, что стоит поправить через
pre_get_posts
Пошаговое решение: пример фильтрации главной страницы по исключению категории
Задача: исключить из главной страницы записи из категории с ID 15.
function exclude_category_from_home( \WP_Query $query ) {
if ( ! is_admin() && $query->is_main_query() && $query->is_home() ) {
// Исключаем категорию с ID 15
$query->set('cat', '-15');
}
}
add_action('pre_get_posts', 'exclude_category_from_home');Объяснение:
- Проверяем, что мы не в админке (
! is_admin()) - Работаем только с основным запросом (
$query->is_main_query()) - Применяем только на главной странице (
$query->is_home()) - Через параметр
catпередаём ID категории со знаком минус для исключения
Другой пример — добавление пользовательского мета-запроса
Если нужно показывать только записи, где мета-поле featured равно 1 на странице архива кастомного типа записей product:
function filter_products_by_meta( \WP_Query $query ) {
if ( ! is_admin() && $query->is_main_query() && is_post_type_archive('product') ) {
$meta_query = array(
array(
'key' => 'featured',
'value' => '1',
'compare' => '=',
),
);
$query->set('meta_query', $meta_query);
}
}
add_action('pre_get_posts', 'filter_products_by_meta');Как проверить, что фильтр сработал
- Откройте страницу, на которую воздействует фильтр (например, главную)
- Убедитесь, что записи из исключённых категорий не отображаются
- Для проверки мета-запроса проверьте, что выводятся только записи с заданным мета-полем
- Включите режим отладки: добавьте
var_dump($query->request)в файлfunctions.phpпосле установки параметров в фильтре, чтобы увидеть SQL-запрос - Проверьте пагинацию — она должна работать корректно после применения фильтра
Частые ошибки при использовании pre_get_posts и их исправление
- Изменение не основного запроса: не используйте фильтр без проверки
is_main_query(), иначе изменятся все запросы, в том числе в админке и сайдбарах. - Применение в админке: фильтр сработает на все запросы в админке, если не добавить
! is_admin(). - Неправильные параметры запроса: для исключения категорий используйте знак минус перед ID (
-15), иначе записи будут фильтроваться наоборот. - Нарушение пагинации: если после фильтрации пагинация не работает, проверьте, что фильтр применяется только к основному запросу и не меняет параметры, влияющие на количество постов.
Практические советы для безопасности и производительности
- Используйте кэширование запросов, например, с помощью Object Cache или плагинов кеша, чтобы уменьшить нагрузку от сложных фильтров.
- Избегайте сложных
meta_queryс большим количеством условий без индексации базы данных, так как они сильно замедляют запросы. - Не добавляйте тяжелые вычисления или внешние запросы внутри
pre_get_posts, это влияет на время загрузки. - Всегда ограничивайте область действия фильтра с помощью проверок
is_admin(),is_main_query()и условий для страниц.
Сравнение способов фильтрации запросов в WordPress
| Метод | Описание | Плюсы | Минусы |
|---|---|---|---|
pre_get_posts | Изменение основного запроса через хук | Глобальное, корректно работает с пагинацией, без дублирования WP_Query | Требует точных условий, можно повлиять на другие запросы по ошибке |
Новый WP_Query | Создание нового запроса для выборки | Локальный контроль, можно получать любые данные | Проблемы с пагинацией, дублирование кода, сложнее поддерживать |
| Плагины фильтрации | Готовые решения с интерфейсом | Удобство, нет нужды писать код | Нагрузка, ограниченные возможности кастомизации |