Что такое хук pre_get_posts и зачем он нужен
Хук pre_get_posts позволяет изменить главный WP_Query до выполнения запроса к базе. С его помощью можно фильтровать записи, изменять параметры выборки, например, ограничить вывод по категориям, меткам, типу записи и другим условиям. Это самый гибкий способ программно влиять на контент, который выводится на фронтенде и в административной части.
Диагностика: когда нужен pre_get_posts
Если на сайте WordPress нужно:
- показывать на главной странице или архиве только определённые записи;
- исключать из вывода записи по определённым условиям (например, по меткам, авторам, пользовательским полям);
- менять сортировку или количество записей;
- фильтровать результаты поиска;
— то pre_get_posts — ваш инструмент. Если пытаться менять query_posts() или другие методы, это может привести к ошибкам и конфликтам.
Пошаговое решение: базовое использование pre_get_posts
1. Добавляем функцию в файл functions.php вашей темы
function wpboot_filter_main_query( \WP_Query $query ) {
// Применяем только к главному запросу на фронтенде
if ( ! is_admin() && $query->is_main_query() ) {
// Пример: выводим только записи из категории с ID 5
$query->set( 'cat', 5 );
// Можно изменить количество постов на 10
$query->set( 'posts_per_page', 10 );
}
}
add_action( 'pre_get_posts', 'wpboot_filter_main_query' );2. Проверяем работу
Откройте главную страницу сайта в браузере. Вы должны увидеть только записи из категории с ID 5 и не более 10 штук. Если изменений нет, проверьте, что функция подключена и не перезаписывается другими плагинами.
Расширенные примеры фильтрации
Фильтрация по метаполю (кастомному полю)
function wpboot_filter_by_meta_key( \WP_Query $query ) {
if ( ! is_admin() && $query->is_main_query() && is_post_type_archive( 'product' ) ) {
$meta_query = [
[
'key' => 'in_stock',
'value' => '1',
'compare' => '=',
],
];
$query->set( 'meta_query', $meta_query );
}
}
add_action( 'pre_get_posts', 'wpboot_filter_by_meta_key' );Этот код на архиве типа записи “product” отфильтрует товары, у которых метаполе in_stock равно 1.
Проверка результата после внедрения
Для проверки результата:
- Откройте страницу, на которую влияет фильтр (например, главную или архив);
- Выведите в шаблоне
var_dump($wp_query->request)для отладки SQL-запроса; - Проверьте в админке, что фильтрация не влияет на административные запросы (если это не нужно);
- Воспользуйтесь плагином Query Monitor для мониторинга запросов и фильтров.
Частые ошибки и как их исправить
- Использование pre_get_posts без проверки is_main_query()
Без проверки фильтр может применяться к вспомогательным запросам, ломая вывод других элементов. Всегда добавляйтеif ($query->is_main_query()). - Не учитывается is_admin()
Если не исключить админку (! is_admin()), фильтрация затронет запросы в панели, что может привести к ошибкам. - Неверные параметры запроса
Параметры должны соответствовать WP_Query. Например, для категорий используйтеcatс ID илиcategory_nameс ярлыком. - Конфликты с другими плагинами или темами
Проверьте, не перезаписывают ли другие фильтры запросы. Отключите плагины поочерёдно для диагностики.
Практические советы по производительности и безопасности
- Минимизируйте количество сложных метазапросов (meta_query), они замедляют SQL.
- Используйте кеширование результатов WP_Query (например, объектный кеш) для часто запрашиваемых страниц.
- Не создавайте бесконечные циклы — pre_get_posts меняет запросы, будьте внимательны при вызове новых запросов внутри фильтра.
Сравнение способов фильтрации контента в WordPress
| Метод | Преимущества | Недостатки |
|---|---|---|
| pre_get_posts | Гибкая фильтрация, работает до запроса, не влияет на шаблоны | Требует аккуратности, может конфликтовать с другими фильтрами |
| query_posts() | Простой вызов переопределения запроса | Перезаписывает глобальный запрос, может ломать пагинацию |
| WP_Query внутри шаблона | Изолированный запрос, не влияет на главный запрос | Дополнительные запросы к БД, повышенная нагрузка |