Одна из основных фишек WordPress – циклы. Ведь по сути именно основной цикл определяет, какой контент выводить на странице. Но иногда бывает нужно как-то изменить контент, выводимый циклом по умолчанию. Может быть добавить произвольный тип записи в вывод, или наоборот, исключить какие-то конкретные посты. Это можно сделать, изменив запрос этого цикла.
Чтобы лучше понимать работу циклов в WordPress, можете посмотреть мой видеоурок по циклам, который является частью моего курса по натяжке вёрстки на WordPress.
Так вот, все модификации основного цикла легко и просто делаются хуком pre_get_posts
, если точнее, то вы можете сделать например вот что:
Давайте теперь по порядку разберёмся, как с этим работать.
Важно понимать – хук pre_get_posts
срабатывает для всех-всех-всех циклов на вашем сайте, даже для тех, которые находятся в админке. Поэтому при помощи условий и условных тегов нам нужно настроиться на определённый цикл.
Например, если мы хотим изменить только основной цикл на страницах категорий, то мы должны:
$query->is_main_query()
, чтобы приконнектиться только к основному циклу, а не к дополнительному,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
, передаваемой в хук.
Например в примере ниже на основной странице блога мы исключаем все посты, которые содержатся в рубрике с 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 ) ); } }
Не знаете, что делать с этим кодом?
Предположим, что у вас зарегистрирован тип записи, например 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' ); } } }
Не знаете, что делать с этим кодом?
Для достижения этой цели воспользуемся 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', ) ) ); } }
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 на основе какого-то дизайна, то рекомендую вам мой видеокурс.
Чтобы оставить комментарий, пожалуйста, зарегистрируйтесь или войдите.
Очень помог - спасибо
1. А Вы не путаете в этой статье между собой Основной цикл и Основной запрос?
2. pre_get_posts, кстати, действует и на результаты get_posts()
1. Спасибо за уточнение. В целом loop и query не одно и то же, но при переводе и объяснении иногда бывает легче ограничиться одним понятием, нежели двумя. Дополнил пост уточнениями.
2. Да