Диагностика проблемы: почему стандартные запросы WP_Query не подходят
Часто в проектах на WordPress возникает необходимость изменить стандартные запросы — например, исключить определённые категории из главной ленты, добавить сортировку по метаполю или изменить количество выводимых записей. Многие пытаются сделать это через хуки, но без правильного понимания pre_get_posts возникают ошибки или изменения не применяются.
Проверить, что запрос не меняется, можно, добавив в файл functions.php следующий код:
add_action('pre_get_posts', function($query) {
if ($query->is_main_query()) {
error_log('Main query fired: '.print_r($query, true));
}
});Если в логе не появляется запись, значит ваш код не срабатывает или не на том этапе.
Пошаговое решение: корректное применение pre_get_posts
1. Проверяем контекст запроса
В функции-обработчике pre_get_posts всегда проверяйте, что изменяете именно главный запрос и что это фронтенд, чтобы не повлиять на админку и сторонние запросы:
add_action('pre_get_posts', 'custom_modify_main_query');
function custom_modify_main_query($query) {
if (is_admin() || !$query->is_main_query()) {
return;
}
// Ваши изменения
}2. Изменяем параметры запроса
Пример: исключить из главной ленты категорию с ID 10 и отсортировать записи по дате в обратном порядке:
function custom_modify_main_query($query) {
if (is_admin() || !$query->is_main_query()) {
return;
}
if ($query->is_home()) {
$query->set('cat', '-10'); // минус значит исключить категорию
$query->set('orderby', 'date');
$query->set('order', 'DESC');
$query->set('posts_per_page', 5);
}
}
add_action('pre_get_posts', 'custom_modify_main_query');3. Обработка кастомных типов записей и таксономий
Для CPT и таксономий логика аналогична, но стоит дополнительно проверять их с помощью is_post_type_archive() или is_tax():
function modify_cpt_query($query) {
if (is_admin() || !$query->is_main_query()) {
return;
}
if ($query->is_post_type_archive('product')) {
$query->set('posts_per_page', 12);
$query->set('meta_key', '_price');
$query->set('orderby', 'meta_value_num');
$query->set('order', 'ASC');
}
}
add_action('pre_get_posts', 'modify_cpt_query');Проверка результата после внедрения
Чтобы убедиться, что изменения применились:
- Откройте соответствующую страницу (например, главную или архив CPT).
- Проверьте количество и порядок записей.
- Включите отладку, добавив в
wp-config.phpdefine('WP_DEBUG', true); define('WP_DEBUG_LOG', true);и вставьтеerror_logв обработчик для логирования параметров запроса. - Используйте Query Monitor — плагин для продвинутого анализа запросов.
Частые ошибки и как их исправить
- Отсутствие проверки
is_main_query(): приводит к изменению всех запросов, в том числе в админке, что вызывает баги. - Изменение параметров после запроса:
pre_get_postsдолжен использоваться до запуска запроса, не меняйте параметры позднее. - Неправильный приоритет хука: иногда нужно указать более высокий приоритет, например,
add_action('pre_get_posts', 'func', 20);, чтобы переопределить другие изменения. - Использование неправильных условий: проверяйте, что условие точно соответствует нужной странице, например,
is_home()vsis_front_page().
Практические советы по производительности и безопасности
- Избегайте сложных тяжелых фильтров в
pre_get_posts, которые ухудшают скорость загрузки. - При работе с метаполями используйте индексы в базе данных и избегайте
meta_queryс большим числом условий. - Не меняйте запросы в админке, чтобы не сломать функционал.
Сравнение подходов изменения запросов
| Способ | Описание | Плюсы | Минусы |
|---|---|---|---|
| pre_get_posts | Изменение параметров главного запроса на этапе подготовки | Гибко, без плагинов, применимо к любым запросам | Требует аккуратности, можно сломать запросы |
| WP_Query | Создание кастомных запросов в шаблонах | Полный контроль, не влияет на главный запрос | Нужно менять шаблоны, дублирование кода |
| Плагины (например, Query Wrangler) | Графический интерфейс для изменения запросов | Удобно для новичков, быстро | Перегружает сайт, не всегда гибко |