Что такое фильтр pre_get_posts и зачем он нужен
Фильтр pre_get_posts позволяет изменять параметры основного и дополнительных запросов WordPress до их выполнения. С его помощью можно оптимизировать выборку записей, исключить ненужные данные или добавить условия, что важно для производительности и корректности вывода контента.
Диагностика проблемы: медленные или избыточные запросы
Если ваш сайт WordPress тормозит при загрузке страниц с архивами, категориями, поиском или пользовательскими типами записей, возможно, запросы WP_Query выполняют лишнюю работу. Часто это связано с отсутствием фильтрации по нужным параметрам, например, выборка всех записей без ограничения таксономий или статусов, что приводит к большому количеству данных и замедлению.
Для диагностики используйте плагин Query Monitor. Он покажет список запросов к базе, время их выполнения и параметры. Анализируйте медленные запросы и ищите возможности их оптимизировать.
Пошаговое решение: добавляем фильтр pre_get_posts
Рассмотрим пример оптимизации главного запроса на странице категории. Задача — исключить из вывода записи с определённым мета-ключом или статусом, а также ограничить количество выводимых записей для ускорения загрузки.
function optimize_category_query(\WP_Query $query) {
if (is_admin() || !$query->is_main_query()) {
return; // Не изменяем запрос в админке и неосновные запросы
}
if ($query->is_category()) {
// Исключаем записи с мета-ключом 'exclude_from_cat' = '1'
$meta_query = [
[
'key' => 'exclude_from_cat',
'compare' => '!=',
'value' => '1'
]
];
$query->set('meta_query', $meta_query);
// Ограничиваем количество записей на странице
$query->set('posts_per_page', 10);
// Явно указываем статус публикации
$query->set('post_status', 'publish');
}
}
add_action('pre_get_posts', 'optimize_category_query');Этот код добавляем в файл functions.php вашей темы или в кастомный плагин. Он проверяет, что запрос основной и не в админке, затем для категории добавляет условие исключения по мета-ключу, ограничивает количество записей и устанавливает статус.
Пример более сложного условия с несколькими параметрами
function optimize_search_query(\WP_Query $query) {
if (is_admin() || !$query->is_main_query()) {
return;
}
if ($query->is_search()) {
// Исключаем страницы из результатов поиска
$query->set('post_type', 'post');
// Добавляем мета-запрос для фильтрации по кастомному полю
$query->set('meta_query', [
[
'key' => 'custom_field',
'value' => 'allowed',
'compare' => '='
]
]);
// Уменьшаем количество результатов
$query->set('posts_per_page', 5);
}
}
add_action('pre_get_posts', 'optimize_search_query');Как проверить, что фильтр сработал
- Откройте нужную страницу (например, категорию или поиск) и убедитесь, что количество записей соответствует заданному лимиту.
- Используйте Query Monitor для проверки параметров запроса — там должны отображаться изменённые настройки (
meta_query,posts_per_page,post_status). - Проверьте, что записи с заданным мета-ключом исключены из вывода.
Частые ошибки при работе с pre_get_posts
- Изменение запросов в админке. Это может привести к сбоям, поэтому всегда проверяйте
is_admin(). - Отсутствие проверки основного запроса. Фильтр срабатывает на все запросы, поэтому используйте
$query->is_main_query()для ограничения. - Перезапись уже заданных параметров. Например, если тема или плагины уже модифицируют запрос, ваши изменения могут конфликтовать. В этом случае стоит использовать приоритет хука выше (например, 20).
- Неправильный синтаксис мета-запросов. Для нескольких условий используйте массивы с правильной структурой.
Практические советы по производительности и безопасности
- Добавляйте только необходимые условия, чтобы не создавать избыточных сложных запросов.
- Используйте
posts_per_pageдля ограничения выборки и избегайте вывода слишком большого количества записей. - Кэшируйте результаты запросов с помощью Transients API или внешних кешей, если данные не меняются часто.
- Проверяйте вводимые параметры, если они зависят от GET-запросов, чтобы избежать SQL-инъекций.
Сравнение вариантов изменения запросов
| Вариант | Пример | Плюсы | Минусы |
|---|---|---|---|
| Использовать pre_get_posts | Изменение параметров основного запроса | Гибко, работает для основного и дополнительных запросов | Нужно аккуратно фильтровать, чтобы не сломать админку |
| Делать отдельный WP_Query | Новый запрос с нужными параметрами | Контролируемый, не влияет на основной запрос | Может быть дублирование запросов, нагрузка на базу |
| Использовать плагины оптимизации запросов | Clearfy Pro, WP Rocket | Простота, дополнительные функции кэширования | Меньше контроля, возможны конфликты |