Что такое фильтр pre_get_posts и зачем он нужен
Фильтр pre_get_posts позволяет изменять параметры основного WP_Query до выполнения запроса к базе данных. Это мощный инструмент для разработчиков, позволяющий гибко настраивать выборки записей, например, для изменения списка записей на главной странице, в архиве или в админке.
Диагностика: почему стандартный запрос не подходит
Часто возникает задача изменить стандартный вывод записей без создания отдельного WP_Query. Пример: вывести на главной странице только записи определённого типа или с определённой категорией. Если стандартный запрос возвращает слишком много данных или не учитывает нужные условия, pre_get_posts поможет.
Пошаговое решение: как правильно использовать pre_get_posts
1. Подключение фильтра в functions.php
function modify_main_query( \WP_Query $query ) {
// Проверяем, что это не запрос в админке и основной запрос
if ( !is_admin() && $query->is_main_query() ) {
// Пример: показать только записи типа 'post' с категорией ID 5
if ( is_home() ) {
$query->set( 'post_type', 'post' );
$query->set( 'cat', 5 );
$query->set( 'posts_per_page', 10 );
}
}
}
add_action( 'pre_get_posts', 'modify_main_query' );2. Пример фильтрации архива кастомного типа записей
function filter_custom_post_type_archive( \WP_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', 20 );
}
}
add_action( 'pre_get_posts', 'filter_custom_post_type_archive' );Проверка результата после внедрения
- Откройте фронтенд сайта, где меняли запрос (например, главная страница или архив).
- Проверьте, что отображается нужный набор записей (тип, категория, фильтры по мета-данным).
- Включите WP_DEBUG и добавьте временный вывод параметров запроса для отладки:
add_action('pre_get_posts', function($query) {
if (!is_admin() && $query->is_main_query()) {
error_log(print_r($query->query_vars, true));
}
});Частые ошибки при работе с pre_get_posts и их исправление
- Ошибка: Изменения не применяются.
Причина: не проверяется$query->is_main_query()или условиеis_admin().
Исправление: добавьте проверку, чтобы изменения применялись только к основному запросу и не в админке. - Ошибка: Изменения влияют на админ-панель.
Причина: отсутствует проверка!is_admin().
Исправление: добавьте проверкуif (!is_admin()). - Ошибка: Конфликты с другими плагинами, меняющими запрос.
Исправление: используйте приоритеты вadd_actionи старайтесь минимизировать условия в фильтре.
Практические советы по безопасности и производительности
- Не выполняйте тяжелые операции внутри фильтра, так как он вызывается при каждом запросе.
- Используйте кеширование (например, Transients API) для результатов сложных запросов, если это возможно.
- Всегда проверяйте, что ваш фильтр не затрагивает административные запросы, чтобы избежать сбоев в админке.
- Избегайте добавления слишком сложных мета-запросов без индексации базы данных — это может замедлить сайт.
Сравнение способов изменения запросов
| Метод | Плюсы | Минусы | Пример |
|---|---|---|---|
pre_get_posts | Изменяет основной запрос без создания нового | Сложнее отладить, влияет на все места, где вызывается запрос | Изменение главной страницы |
| Создание нового WP_Query | Контролируемый новый запрос, не влияет на основной | Нужно вручную выводить результаты | Вывод кастомных записей в шаблоне |
| Использование плагинов фильтрации | Быстро, без кода | Меньше гибкости, возможны конфликты | Плагины для фильтрации WooCommerce |