Что такое хук pre_get_posts и зачем он нужен
Хук pre_get_posts — это один из самых мощных инструментов для изменения стандартных запросов WordPress до их выполнения. Он позволяет модифицировать параметры WP_Query, отвечающего за выборку постов, страниц, товаров WooCommerce и других типов записей без необходимости писать сложные запросы с нуля.
Этот хук часто используется для изменения ленты записей на главной странице, страницах категорий, поисковых запросах и любых других местах, где WordPress формирует запрос к базе данных.
Диагностика задачи: когда использовать pre_get_posts
Если вам нужно:
- изменить количество постов на странице архива или главной;
- показать определённый тип записей (например, только товары WooCommerce);
- отфильтровать записи по метаданным или таксономиям без создания отдельного WP_Query;
- исключить определённые записи из вывода;
- изменить порядок сортировки записей;
— значит, pre_get_posts подходит идеально.
Проверить, что именно формируется запрос, можно с помощью отладки:
add_action('pre_get_posts', function($query) {
if ($query->is_main_query() && !is_admin()) {
error_log(print_r($query, true));
}
});
Логи будут в debug.log, если включён WP_DEBUG_LOG.
Пошаговое решение: пример изменения главного запроса
Допустим, нужно на главной странице вывести только 5 последних постов из категории «Новости» и исключить записи с тегом «архив».
add_action('pre_get_posts', 'wpfront_modify_main_query');
function wpfront_modify_main_query($query) {
if ($query->is_main_query() && !is_admin() && $query->is_home()) {
$query->set('posts_per_page', 5);
$query->set('category_name', 'novosti');
$query->set('tag__not_in', array(get_term_by('slug', 'arhiv', 'post_tag')->term_id));
}
}
Объяснение:
$query->is_main_query()— проверка, что меняется основной запрос.!is_admin()— исключаем админ-панель.$query->is_home()— таргетируем главную страницу.- Далее через
setменяем параметры запроса.
Изменение запроса WooCommerce
Для изменения вывода товаров на странице магазина:
add_action('pre_get_posts', 'wpfront_modify_shop_query');
function wpfront_modify_shop_query($query) {
if (!is_admin() && $query->is_main_query() && is_post_type_archive('product')) {
// Показывать только товары с ценой > 1000
$meta_query = array(
array(
'key' => '_price',
'value' => 1000,
'compare' => '>',
'type' => 'NUMERIC'
)
);
$query->set('meta_query', $meta_query);
$query->set('posts_per_page', 12);
}
}
Как проверить, что изменения работают
- Убедитесь, что код добавлен в
functions.phpтемы или в кастомный плагин. - Очистите кеш сайта и браузера.
- Обновите страницу, на которую направлен запрос (например, главную или архив товаров).
- Проверьте, что изменилось количество или фильтрация постов.
- Если нужно, включите
WP_DEBUGиWP_DEBUG_LOGдля отладки.
Частые ошибки при работе с pre_get_posts и их решения
- Изменение не работает на странице админки: Не забывайте проверять
!is_admin(), чтобы не влиять на запросы в панели управления. - Применяется не к главному запросу: Всегда используйте
$query->is_main_query()для точного таргетинга. - Неверные параметры запроса: Проверьте, что используете правильные ключи и значения. Например,
tag__not_inпринимает массив ID тегов, а не слаг. - Проблемы с мета-запросами: Метаполя должны существовать и быть правильно типизированы (например, 'NUMERIC' для чисел).
Практические советы по безопасности и производительности
- Не используйте
pre_get_postsдля сложных выборок с большими мета-запросами без индексов — это замедлит сайт. - Ограничивайте области действия хука через проверки, чтобы не влиять на лишние запросы.
- Избегайте тяжелых функций и лишних циклов внутри функции, подключенной к
pre_get_posts. - При необходимости используйте transient API для кеширования результатов сложных запросов.
Сравнение способов изменения запросов WordPress
| Метод | Плюсы | Минусы | Когда использовать |
|---|---|---|---|
pre_get_posts | Изменяет основной запрос без перезаписи шаблонов, гибко | Нужно правильно фильтровать запросы, сложнее отладка | Для изменения отображения стандартных архивов и страниц |
| Создание нового WP_Query | Полный контроль, можно создавать дополнительные выборки | Не влияет на основной запрос, дублирование кода | Для вывода дополнительных блоков на странице |
| WP_Query с фильтрами SQL | Максимальная гибкость | Сложно поддерживать, риски безопасности | Когда нужны нестандартные запросы, не поддерживаемые API |