Фильтр pre_get_posts является мощным инструментом для изменения основных и дополнительных запросов WordPress перед их выполнением. С его помощью можно кастомизировать выборку постов, изменять параметры запроса, добавлять условия и создавать уникальные виды отображения контента без необходимости создавать сложные WP_Query с нуля.
Что такое pre_get_posts и где он применяется
Фильтр pre_get_posts срабатывает в момент формирования объекта WP_Query, но до выполнения основного SQL-запроса. Это значит, что можно изменить параметры, которые WordPress использует для выборки постов.
Применяется он как для главного запроса (main query), который отвечает за контент на странице, так и для любых дополнительных запросов, созданных через WP_Query.
Например, с помощью pre_get_posts можно:
- Отфильтровать записи по произвольному метаполю;
- Исключить определённые категории из архивов;
- Изменить порядок сортировки постов;
- Добавить произвольные условия для кастомных типов записей;
- Ограничить количество выводимых записей.
Как правильно использовать фильтр pre_get_posts для главного запроса
Чтобы изменить параметры главного запроса, необходимо добавить обработчик к фильтру pre_get_posts, проверить, что это именно главный запрос и нужная нам страница, а затем изменить параметры.
Пример: изменим главную страницу сайта так, чтобы показывались только записи из категории с ID 10 и сортировка была по дате в порядке убывания.
add_action('pre_get_posts', 'wproot_pre_get_posts_modify_main_query');
function wproot_pre_get_posts_modify_main_query(\WP_Query $query) {
if (!is_admin() && $query->is_main_query() && is_home()) {
$query->set('cat', 10); // категория с ID 10
$query->set('orderby', 'date');
$query->set('order', 'DESC');
}
}Здесь мы используем проверку !is_admin() чтобы не менять запросы в админке, $query->is_main_query() — чтобы не трогать дополнительные запросы, и is_home() — чтобы изменение применялось только на главной странице.
Изменение параметров для архивов кастомного типа записи
Если у вас есть кастомный тип записи, например product, и нужно на архивной странице выводить только товары с ценой больше определённого значения, то в pre_get_posts можно добавить мета-запрос:
add_action('pre_get_posts', 'wproot_modify_product_archive_query');
function wproot_modify_product_archive_query(\WP_Query $query) {
if (!is_admin() && $query->is_main_query() && is_post_type_archive('product')) {
$meta_query = array(
array(
'key' => '_price',
'value' => 1000,
'compare' => '>',
'type' => 'NUMERIC'
)
);
$query->set('meta_query', $meta_query);
$query->set('orderby', 'meta_value_num');
$query->set('meta_key', '_price');
$query->set('order', 'ASC');
}
}Это полезно для интернет-магазинов на WooCommerce, где тип записи product и цена хранится в метаполе _price.
Особенности работы с дополнительными WP_Query
Фильтр pre_get_posts срабатывает и для дополнительных запросов, которые вы создаёте вручную. Важно убедиться, что изменения применяются только к нужным запросам, чтобы не сломать другие части сайта.
Чтобы ограничить действие, можно проверить наличие определённого параметра в запросе, например кастомного параметра my_custom_query:
add_action('pre_get_posts', 'wproot_modify_custom_query');
function wproot_modify_custom_query(\WP_Query $query) {
if (!is_admin() && $query->get('my_custom_query')) {
$query->set('posts_per_page', 5);
$query->set('orderby', 'title');
$query->set('order', 'ASC');
}
}И при создании запроса передавать параметр:
$custom_query = new WP_Query(array(
'post_type' => 'post',
'my_custom_query' => true,
// другие параметры
));Как избежать ошибок и конфликтов при использовании pre_get_posts
При использовании фильтра важно не забывать:
- Всегда проверять
$query->is_main_query()или другие условия, чтобы не изменить лишние запросы. - Вызывать добавление обработчика в
functions.phpили в плагине, чтобы код был загружен вовремя. - Использовать
!is_admin(), чтобы не менять запросы в админке. - Тестировать на разных страницах и типах запросов.
Пример комплексного использования с несколькими условиями
Допустим, нужно на главной странице показывать только опубликованные записи из категории 5 и 7, упорядоченные по дате, а на странице архива кастомного типа event — только будущие события, где дата хранится в метаполе event_date.
add_action('pre_get_posts', 'wproot_complex_query_modifications');
function wproot_complex_query_modifications(\WP_Query $query) {
if (!is_admin() && $query->is_main_query()) {
if (is_home()) {
$query->set('cat', '5,7');
$query->set('orderby', 'date');
$query->set('order', 'DESC');
$query->set('post_status', 'publish');
}
if (is_post_type_archive('event')) {
$meta_query = array(
array(
'key' => 'event_date',
'value' => date('Y-m-d'),
'compare' => '>=',
'type' => 'DATE'
)
);
$query->set('meta_query', $meta_query);
$query->set('orderby', 'meta_value');
$query->set('meta_key', 'event_date');
$query->set('order', 'ASC');
}
}
}Полезные плагины для работы с запросами и фильтрами
Хотя pre_get_posts позволяет гибко менять запросы, иногда удобно использовать плагины для упрощения задач:
- Query Monitor — помогает отлаживать запросы и видеть SQL-запросы, которые выполняются на странице;
- Clearfy Pro — оптимизация и управление функционалом, в том числе и запросами;
- WPRemark — расширенные возможности для комментариев и запросов.
Заключение по использованию pre_get_posts
Фильтр pre_get_posts — это основной инструмент для тонкой настройки запросов WordPress без необходимости полностью переписывать логику выборки постов. Его правильное использование позволяет реализовать задачи любой сложности: от простого исключения категорий до сложных мета-запросов для кастомных типов записей.
Главное — внимательно контролировать, к каким запросам применяется фильтр, и тестировать изменения, чтобы не нарушить работу сайта.