pre_get_posts

Наиболее правильным способом изменить основной цикл WordPress является хук (событие) pre_get_posts, которое происходит перед каждым запросом WP_Query. Работать с этим событием можно в плагине или в файле functions.php вашей темы:

Важно отметить, что pre_get_posts вызывается для каждого запроса WP_Query, включая основной запрос, навигационное меню, вторичные запросы в виджетах и пр. С помощью метода is_main_query() мы изменяем параметры только основного запроса, а с помощью проверки is_admin() мы меняем запрос только на фронтенд части сайта, а не в админке.

Важно убедиться, что вы изменяете именно нужный вам запрос, для этого перед изменением запроса используйте всевозможные условные теги, чтобы точно ограничить изменение.

Событие pre_get_posts дает возможность изменять объект $wp_query, потому что объект передается в хук по ссылке (&), это означает, что любые действия над $query внутри функции буду влиять на основной объект $wp_query. Для этого хука не надо возвращать никаких данных.

Объект $query предается по ссылке, поэтому нет необходимости определять глобальную переменную. Любые изменения $query внутри функции влияют сразу на оригинальный объект.

pre_get_posts нельзя использовать для изменения запросов связанных с постоянными страницами, потому что ‘is_page’, ‘is_singular’, ‘pagename’ и другие параметры (зависимые от ЧПУ) уже установлены в объекте. Также нельзя использовать в файлах шаблонов темы (например archive.php), так как они загружаются уже после выполнения основного запроса. Рекомендуется использовать new WP_Query в шаблоне постоянной страницы, чтобы изменить запрос.

При использовании pre_get_posts, вы должны точно определить в какой конкретно запрос вы вносите изменения. Например, мы хотим изменить запрос на странице категорий и не делаем проверку is_category(), тогда наши изменения будут влиять на формирования запроса в админ-панели, на других страницах сайта и везде, где используется основной цикл.

pre_get_posts срабатывает до того, как объект WP_Query полностью определится. Поэтому некоторые условные теги, опирающиеся на данные WP_Query еще не работают. Например, is_front_page() не работает, тогда как is_home() будет работать. Поэтому вам лучше работать с данными объекта напрямую ($query->is_search).

Примеры

Исключение постоянных страниц из результатов поиска

Включение произвольного типа записей в результаты поиска

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