Что такое фильтр pre_get_posts и зачем он нужен
Фильтр pre_get_posts позволяет изменить основной WP_Query до выполнения запроса к базе данных. Это мощный инструмент для контроля вывода постов, например, на главной странице, в архивах, категориях или на страницах произвольных типов записей.
Часто возникает задача изменить количество записей, добавить фильтрацию по мета-данным или исключить определённые записи из выборки. Использование pre_get_posts — правильный способ сделать это, не нарушая логику WordPress и не меняя шаблоны.
Диагностика: как понять, что pre_get_posts работает неправильно
- Изменения в запросе не применяются — выводятся стандартные записи без изменений.
- Изменился не тот запрос — например, вы хотели изменить главную страницу, а изменился запрос в админке.
- Появились ошибки или некорректный вывод данных.
Для диагностики полезно включить вывод SQL-запросов с помощью плагина Query Monitor или добавить отладочный вывод в код.
Пошаговое решение: корректное применение pre_get_posts
1. Проверка, что это основной запрос и фронтенд
function modify_main_query( $query ) {
if ( is_admin() || ! $query->is_main_query() ) {
return;
}
// Дальше — условия для изменения запроса
}
add_action( 'pre_get_posts', 'modify_main_query' );Обязательно проверяйте is_main_query(), иначе можно случайно поменять запросы в админке или второстепенные запросы, что приведёт к ошибкам.
2. Пример: изменить количество постов на главной странице
function change_posts_per_page_on_home( $query ) {
if ( is_admin() || ! $query->is_main_query() ) {
return;
}
if ( $query->is_home() ) {
$query->set( 'posts_per_page', 5 );
}
}
add_action( 'pre_get_posts', 'change_posts_per_page_on_home' );Этот код изменит число записей на главной странице с дефолтных 10 до 5.
3. Пример: исключить определённую категорию из архива
function exclude_category_from_archive( $query ) {
if ( is_admin() || ! $query->is_main_query() ) {
return;
}
if ( $query->is_archive() ) {
$query->set( 'cat', '-12' ); // исключаем категорию с ID 12
}
}
add_action( 'pre_get_posts', 'exclude_category_from_archive' );Проверка результата после внедрения
- Откройте страницу, для которой меняли запрос (например, главную или архив).
- Проверьте количество записей или наличие/отсутствие записей из исключённых категорий.
- Для сложных изменений включите Query Monitor и посмотрите фактический SQL-запрос.
Частые ошибки и как их исправить
- Не используется
is_main_query(): приводит к изменениям в побочных запросах, могут сломаться виджеты или админка. - Изменение запроса в админке: добавляйте проверку
is_admin(), чтобы код работал только на фронтенде. - Неправильные параметры запроса: например, ошибочный ID категории или опечатки в параметрах
set(). Проверяйте значения и документацию WP_Query.
Практические советы по безопасности и производительности
- Не вызывайте тяжелые функции внутри
pre_get_posts, чтобы не замедлять загрузку страниц. - Используйте точные условия (например,
is_home(),is_archive()), чтобы не менять запросы без необходимости. - Кэшируйте результаты, если в запросе используются сложные условия мета-запросов.
- Для больших сайтов с WooCommerce учитывайте совместимость с плагином. WooCommerce использует свои запросы, их можно отлавливать через
$query->get('post_type') === 'product'.
Сравнение способов изменения запроса
| Метод | Плюсы | Минусы |
|---|---|---|
pre_get_posts | Гибко меняет запрос без изменения шаблонов, стандартизированный способ | Нужно аккуратно использовать фильтры и проверки |
| Создание нового WP_Query | Полный контроль над запросом, изоляция от основного | Нужно менять шаблоны, дублирование кода |
| Использование плагинов для изменения вывода | Быстро, без кода | Меньше гибкости, возможны конфликты |