WP_Query
Коротко
PHP-класс WordPress, который по набору параметров строит SQL-запрос к записям и возвращает подходящие публикации вместе с данными для пагинации.
Что такое «WP_Query»
Каждая страница WordPress начинается с запроса: ядро разбирает адрес, превращает его в параметры и создаёт объект WP_Query — это главный запрос. По нему шаблон и выводит записи в стандартном Цикле. Тот же класс разработчики используют для дополнительных выборок: «похожие статьи» под записью, шесть товаров со скидкой на главной, последние новости в подвале. Параметры описываются массивом, а SQL с объединением таблиц WordPress составляет сам.
Пример: товары из рубрики
$q = new WP_Query( [
'post_type' => 'product',
'posts_per_page' => 6,
'tax_query' => [ [
'taxonomy' => 'product_cat',
'field' => 'slug',
'terms' => 'sale',
] ],
'no_found_rows' => true, // пагинация не нужна — запрос быстрее
] );
while ( $q->have_posts() ) { $q->the_post(); the_title( '<h3>', '</h3>' ); }
wp_reset_postdata();
Фильтрация по рубрикам и меткам идёт через tax_query — подробнее о группах терминов на странице таксономии, — по произвольным полям через meta_query, по датам через date_query. Вызов wp_reset_postdata() возвращает глобальную переменную $post к записи главного запроса, иначе шаблон дальше выведет чужой заголовок.
Главный запрос не нужно дублировать
Частая ошибка — в шаблоне архива выбросить результат главного запроса и сделать новый, например чтобы показать 20 записей вместо 10. Это двойная работа базы и сломанная пагинация. Правильный путь — изменить главный запрос до выполнения, на хуке pre_get_posts:
add_action( 'pre_get_posts', function ( $query ) {
if ( ! is_admin() && $query->is_main_query() && $query->is_category( 'novosti' ) ) {
$query->set( 'posts_per_page', 20 );
}
} );
Функция query_posts() из старых инструкций делает то же самое плохо — подменяет главный запрос уже после выполнения. В блочных темах аналог WP_Query без кода — блок запроса, который под капотом использует тот же класс.

