Хук pre_get_posts — один из самых мощных инструментов в WordPress для изменения основного запроса без вмешательства в SQL-запросы напрямую. С его помощью можно фильтровать, сортировать и изменять вывод записей на любой странице сайта, будь то главная, архив, поиск или кастомные типы записей.
Что такое хук pre_get_posts и зачем он нужен
По умолчанию WordPress формирует запросы на основе URL и настроек темы. Но иногда нужно изменить логику выборки записей, например, показать только определённые категории на главной, исключить записи с меткой или добавить кастомные параметры сортировки. Для этого и существует хук pre_get_posts, который срабатывает до выполнения SQL-запроса и позволяет модифицировать объект WP_Query.
Преимущества использования pre_get_posts:
- Изменение запросов без создания новых WP_Query.
- Универсальность — можно изменить запросы в любом месте сайта.
- Производительность — изменения происходят до выборки, что эффективнее, чем фильтрация после.
Важно корректно проверять, в каком запросе вы находитесь, иначе можно сломать вывод на админке или на других страницах.
Основные параметры и проверка запроса в хуке pre_get_posts
Вот базовый пример использования хука, который изменяет запрос на главной странице, показывая только записи из категории с ID 5:
add_action('pre_get_posts', 'wpnote_pre_get_posts_filter');
function wpnote_pre_get_posts_filter($query) {
// Проверяем, что это главный запрос и не админка
if (!is_admin() && $query->is_main_query() && is_home()) {
// Ограничиваем выборку только категориями с ID 5
$query->set('cat', 5);
}
}Объяснение:
!is_admin()— исключает изменение запросов в панели управления.$query->is_main_query()— позволяет изменить только основной запрос, а не дополнительные запросы, например в сайдбаре.is_home()— условие для главной страницы блога.$query->set('cat', 5);— задаёт параметр для выбора записей из категории с ID 5.
Без таких проверок можно случайно повлиять на админку или другие запросы, что вызовет ошибки или некорректный вывод.
Примеры практического использования pre_get_posts для фильтрации и сортировки
1. Исключение определённых категорий с главной страницы
Если нужно убрать из главной страницы записи из нескольких категорий, используйте такой код:
add_action('pre_get_posts', 'wpnote_exclude_categories_from_home');
function wpnote_exclude_categories_from_home($query) {
if (!is_admin() && $query->is_main_query() && is_home()) {
$query->set('category__not_in', array(10, 11));
}
}Так мы исключим категории с ID 10 и 11 из главной.
2. Отображение только определённого кастомного типа записи на архиве
Если у вас есть кастомный тип записи product и нужно на странице архива показывать только его, а не обычные записи, то:
add_action('pre_get_posts', 'wpnote_show_only_products_archive');
function wpnote_show_only_products_archive($query) {
if (!is_admin() && $query->is_main_query() && is_post_type_archive('product')) {
$query->set('post_type', 'product');
$query->set('posts_per_page', 20);
}
}Здесь мы явно задаём тип записи и количество выводимых элементов.
3. Сортировка записей по метаполю (custom field)
Для сортировки записей по значению произвольного поля, например price, используем:
add_action('pre_get_posts', 'wpnote_sort_by_custom_field');
function wpnote_sort_by_custom_field($query) {
if (!is_admin() && $query->is_main_query() && is_post_type_archive('product')) {
$query->set('meta_key', 'price');
$query->set('orderby', 'meta_value_num');
$query->set('order', 'ASC');
}
}Важно использовать meta_value_num для числовой сортировки, иначе сортировка будет по строкам.
Особенности и подводные камни при работе с pre_get_posts
Несмотря на простоту, есть важные моменты, которые надо учитывать:
- Всегда проверяйте
is_main_query(), чтобы не ломать дополнительные запросы. - Не изменяйте запрос в админке, если не уверены, иначе можно нарушить работу панели управления.
- Некоторые плагины и темы могут сами использовать
pre_get_posts, что может вызвать конфликты. - При изменении запроса на страницах поиска будьте осторожны, чтобы не убрать нужный контент.
Для отладки удобно использовать плагин Debug Bar или выводить параметры запроса с помощью var_dump($query) в безопасном режиме.
Интеграция с плагинами и инструментами для улучшения фильтрации
Если нужны более сложные фильтры, например, AJAX-подгрузка или умный поиск, можно использовать плагины, которые расширяют WP_Query. Среди таких решений на WPShop.ru есть полезные инструменты для кастомизации запросов и фильтров.
Например, плагин Clearfy Pro позволяет оптимизировать запросы и улучшить производительность сайта, а WPRemark помогает автоматизировать отзывы с фильтрацией по рейтингу, что тоже реализуется через изменение запросов.
Расширенный пример: фильтрация записей с несколькими условиями
Допустим, нужно вывести на странице архива записи, которые принадлежат определённой категории, имеют метаполе featured со значением yes и отсортированы по дате:
add_action('pre_get_posts', 'wpnote_advanced_filtering');
function wpnote_advanced_filtering($query) {
if (!is_admin() && $query->is_main_query() && is_category('news')) {
$meta_query = array(
array(
'key' => 'featured',
'value' => 'yes',
'compare' => '=',
),
);
$query->set('meta_query', $meta_query);
$query->set('orderby', 'date');
$query->set('order', 'DESC');
}
}Здесь мы используем массив meta_query для более сложных условий, что позволяет гибко фильтровать записи.
Итоги и рекомендации по использованию pre_get_posts
Хук pre_get_posts — незаменимый инструмент для разработчиков, позволяющий тонко настраивать логику вывода контента. Используйте его для:
- Фильтрации записей по категориям, таксономиям и метаполям.
- Изменения количества записей на странице.
- Настройки сортировки и порядка вывода.
Обязательно тестируйте свои изменения в разных условиях и следите, чтобы не произошло негативного влияния на админку и производительность.