Диагностика проблемы: когда нужно изменять стандартные запросы WordPress
Часто возникает задача изменить выборку записей на страницах блога, архивов или в виджетах без создания отдельного плагина или кастомного запроса. Например, убрать записи определённой категории с главной, изменить число постов на странице или добавить фильтрацию по метаполям. Для этого WordPress предлагает хук pre_get_posts, который позволяет вмешиваться в основной запрос до его выполнения.
Как работает хук pre_get_posts
pre_get_posts — это фильтр, который срабатывает перед выполнением запроса WP_Query. С помощью него можно модифицировать SQL-запрос, изменяя параметры выборки записей. Он срабатывает как для главного запроса (is_main_query()), так и для дополнительных.
Важно: чтобы не повлиять на административную панель и избежать конфликтов, всегда проверяйте контекст выполнения.
Пример: убрать категорию с главной страницы
function exclude_category_from_home( $query ) {
if ( ! is_admin() && $query->is_main_query() && $query->is_home() ) {
// ID категории, которую нужно исключить
$query->set( 'cat', '-5' );
}
}
add_action( 'pre_get_posts', 'exclude_category_from_home' );В этом коде мы исключаем категорию с ID 5 из главной страницы блога. Минус перед ID означает исключение.
Пошаговое решение: изменение запроса для кастомных условий
Рассмотрим, как изменить число постов на странице архива и добавить фильтр по произвольному полю (meta_key).
- Определите условие страницы в запросе (например, архив категории).
- Проверьте, что это главный запрос, а не админка.
- Используйте методы
$query->set()для изменения параметров.
function modify_archive_query( $query ) {
if ( ! is_admin() && $query->is_main_query() && $query->is_category() ) {
// Устанавливаем 10 записей на страницу
$query->set( 'posts_per_page', 10 );
// Фильтруем по метаполю 'featured' со значением 'yes'
$query->set( 'meta_key', 'featured' );
$query->set( 'meta_value', 'yes' );
}
}
add_action( 'pre_get_posts', 'modify_archive_query' );Проверка результата после внедрения
Чтобы убедиться, что изменения сработали:
- Откройте страницу, для которой меняли запрос (главная, архив).
- Проверьте, что записи соответствуют новым параметрам (например, отсутствует категория, изменено число постов).
- Включите режим отладки и выведите SQL-запрос:
echo $wp_query->request;в файле шаблона. - Используйте плагины типа Query Monitor для наглядного анализа запросов.
Частые ошибки и как их исправить
- Изменение запроса в админке: отсутствие проверки
! is_admin()вызовет баги в панели управления. Исправьте добавлением проверки. - Изменение не главного запроса: без
is_main_query()вы можете изменить сторонний запрос (например, виджета), что приведёт к ошибкам. - Неверное использование параметров: например, установка
catчерез положительное число добавит только эту категорию, а не исключит. Используйте минус для исключения. - Неочевидный конфликт с другими плагинами: если другие хуки тоже меняют запрос, проверьте приоритет добавления функций и используйте
remove_action.
Практические советы по безопасности и производительности
- Не нагружайте запросы сложными мета-запросами без необходимости: они сильно влияют на скорость. Используйте индексы в базе или кэширование.
- Минимизируйте изменения в
pre_get_posts: пишите точные условия, чтобы не ломать другие части сайта. - Тестируйте на staging-сервере: любое изменение запросов может привести к появлению пустых страниц или циклов.
Сравнение способов изменения запросов: плагин vs. pre_get_posts vs. WP_Query
| Способ | Плюсы | Минусы |
|---|---|---|
| pre_get_posts | Изменяет главный запрос без создания нового; гибко; не требует плагинов | Нужно внимательно писать условия; можно сломать другие запросы |
| WP_Query (с кастомным запросом) | Полный контроль над выборкой; можно использовать в шаблонах | Создаёт дополнительный запрос; может ухудшать производительность |
| Плагины для фильтрации контента | Удобно для новичков; готовые решения | Могут быть избыточными; нагрузка на сайт; риск конфликтов |