pre_get_posts – изменение циклов (запросов) в WordPress

Одна из основных фишек WordPress – циклы. Ведь по сути именно основной цикл определяет, какой контент выводить на странице. Но иногда бывает нужно как-то изменить контент, выводимый циклом по умолчанию. Может быть добавить произвольный тип записи в вывод, или наоборот, исключить какие-то конкретные посты. Это можно сделать, изменив запрос этого цикла.

Чтобы лучше понимать работу циклов в WordPress, можете посмотреть мой видеоурок по циклам, который является частью моего курса по натяжке вёрстки на WordPress.

Так вот, все модификации основного цикла легко и просто делаются хуком pre_get_posts, если точнее, то вы можете сделать например вот что:

Давайте теперь по порядку разберёмся, как с этим работать.

Прежде всего нужно настроиться на определённый цикл! Как правильно ставить условия

Важно понимать – хук pre_get_posts срабатывает для всех-всех-всех циклов на вашем сайте, даже для тех, которые находятся в админке. Поэтому при помощи условий и условных тегов нам нужно настроиться на определённый цикл.

Например, если мы хотим изменить только основной цикл на страницах категорий, то мы должны:

add_action( 'pre_get_posts', 'true_modify_category_pages_loop' );
 
function true_modify_category_pages_loop( $query ) {
 
 
	if ( ! is_admin() && $query->is_main_query() ) {
		// не админка
		// и основной цикл страницы
 
		if ( is_category() ) {
			// страница архива рубрик
 
			// например установим 15 записей на странице
			$query->set( 'posts_per_page', 15 );
		}
	}
}

В качестве $query->set() мы используем любые параметры WP_Query. Только не забывайте, что использование параметра offset сломает вам пагинацию.

Также по поводу условий не будет лишним упомянуть – так как pre_get_posts запускается перед непосредственно WP_Query(), то некоторые условные теги, которые зависят от этого класса, могут не работать. Например is_front_page() работать не будет, но зато будет работать is_home(). В таком случае можете прочекать, что находится в переменной $query, передаваемой в хук.

Пример 1. Как исключить вывод постов из определённой рубрики

Например в примере ниже на основной странице блога мы исключаем все посты, которые содержатся в рубрике с ID=152.

add_action( 'pre_get_posts', 'true_exclude_posts_from_cat' );
function true_exclude_posts_from_cat( $query ) {
 
	if ( ! is_admin() && $query->is_main_query() && $query->is_home() ) {
		$query->set( 'category__not_in', array( 152 ) );
	}
}

Не знаете, что делать с этим кодом?

Пример 2. Изменение количества постов на странице для страницы архивов типа записи

Предположим, что у вас зарегистрирован тип записи, например events для каких-либо событий. И при выводе страницы со всеми событиями вы бы хотели, чтобы на ней отображалось нестандартное число постов, скажем 25 событий за раз.

Это тоже можно легко сделать при помощи pre_get_posts.

Для проверки того, что мы находимся на странице архивов типа записи я использовал условный тег is_post_type_archive().

add_action( 'pre_get_posts', 'true_event_posts_per_page' );
function true_event_posts_per_page( $query ) {
 
	if ( ! is_admin() && $query->is_main_query() && is_post_type_archive( 'event' ) ) {
		$query->set( 'posts_per_page', 25 );
	}
}

По умолчанию, когда вы используете поиск на своём сайте WordPress, то в нём отображаются не только записи, но и страницы. Так вот – вы можете исключить их оттуда при помощи того же самого pre_get_posts. Вот так:

add_action( 'pre_get_posts', 'true_exclude_pages_from_search' );
 
function true_exclude_pages_from_search( $query ) {
	// не админка и основной цикл
	if ( ! is_admin() && $query->is_main_query() ) {
		// страница поиска
		if ( $query->is_search ) {
			$query->set( 'post_type', 'post' );
		}
	}
}

Не знаете, что делать с этим кодом?

Пример 4. Выводим в результатах поиска только посты, опубликованные после определённой даты

Для достижения этой цели воспользуемся date_query.

add_action( 'pre_get_posts', 'true_posts_in_search_after_date' ); 
 
function true_posts_in_search_after_date( $query ) {
	// условия
	if ( ! is_admin() && $query->is_main_query() && $query->is_search ) {
 
		$query->set( 'date_query', array(
			array(
 				'after' => 'May 17, 2021', 
			)
 		) );
	}
}

Пример 5. Меняем сортировку записей в рубрике по количеству комментариев

add_action( 'pre_get_posts', 'true_modify_category_pages_loop' );
 
function true_modify_category_pages_loop( $query ) {
 
 
	if ( ! is_admin() && $query->is_main_query() ) {
		// не админка и основной цикл страницы
 
		if ( is_category( 'wordpress' ) ) {
			// страница архива рубрики с ярлыком "wordpress"
 
			// меняем сортировку
			$query->set( 'orderby', 'comment_count' );
			$query->set( 'order', 'DESC' ); // DESC - сначала посты, где больше комментов
		}
	}
}

Не знаете, что делать с этим кодом?

Кстати, если вам интересно более глубоко разобраться в создании темы для WordPress на основе какого-то дизайна, то рекомендую вам мой видеокурс.

Миша

Впервые познакомился с WordPress в 2009 году. Организатор и спикер на конференциях WordCamp. Преподаватель в школе Нетология.

Пишите, если нужна помощь с сайтом или разработка с нуля.

Комментарии — 3

Чтобы оставить комментарий, пожалуйста, зарегистрируйтесь или войдите.

Миша Рудрастых и WordPress

Полезности из мира WordPress и жизни студии.

Мой телеграм-канал