Настройка WordPress — событие pre_get_posts

Всем привет! Сегодня на seo-mayak.com интересная тема — настройка WordPress.

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

Но речь в статье пойдет не о стандартных настройках WordPress, а о дополнительных, тонких настройках, которые можно произвести, благодаря событию pre_get_posts.

А что конкретно можно настроить с помощью события pre_get_posts? Например, можно выводить на главной странице десять анонсов а на страницах: категорий, меток, архивов — пять штук, что безусловно повлияет на общую скорость загрузки, пусть даже в мл/сек.

nastroika-wordpress

Событие pre_get_posts относится к классу WP_Query и чтобы объяснить, как работает хук, придется немного рассказать и о WP_Query.

Само слово «Query» в переводе с англ. означает — запрос. Из названия класса можно понять, чем он занимается.

На заметку! WP_Query — это важный php класс, отвечающий за получение из БД: страниц с записями (single), статических страниц (page) и страниц произвольного типа.

Все эти данные можно объединить в одно слово — контент.

Кто вообще не знаком с понятиями: хук-событие или хук-фильтр, пока почитайте вот эту статью, а в будущем я обязательно напишу отдельный пост, где постараюсь раскрыть тему хуков полностью, так что подписывайтесь на обновления блога.

Итак, давайте поближе познакомимся с событием pre_get_posts. Поехали!

Как работает хук-событие pre_get_posts

Для более детального понимания процесса, давайте рассмотрим такую ситуацию. Пользователь открыл страницу категории «Салаты» и тем самым активировал функционал класса WP_Query.

В свою очередь WP_Query, руководствуясь настройками WoprdPress, делает запрос к БД и получает:

1. Все посты, относящиеся к рубрики «Салаты»;
2. Данные о количестве постов в рубрике «Салаты».
3. Данные о количестве постов, для отображения на одной странице и количество страниц пагинации;

Так какими настройками WoprdPress руководствуется WP_Query? Теми, которые мы сами и установили.

Публикуя очередной пост, мы его привязываем к определенной категории.

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

Количество записей на странице мы устанавливаем в админке (Настройки/Чтение/На страницах блога отображать не более). Тем самым, разбивая общее количество записей, получаем количество страниц пагинации.

Так вот, событие pre_get_posts срабатывает непосредственно перед обращением WP_Query к базе данных и дает нам возможность вносить коррективы в поток информации, которую в итоге получит пользователь.

Надеюсь понятно! Но кажется без конкретных примеров здесь не обойтись.

Как убрать запись из рубрики

Допустим, в категории «Салаты» с ID 10, есть пост с ID 45 (как узнать ID рубрики или статьи), который бы мы не хотели показывать пользователю. В файл functions.php вставляем следующее:

  function mayak_post_exclude($query){  	if ($query->is_category(10))  	$query->set('post__not_in', array(45));  }  add_action('pre_get_posts','mayak_post_exclude');  

Теперь пост с ID 45 не будет отображаться в категории «Салаты», но его по прежнему можно будет найти в архивах или на страницах общей пагинации.

Все это потому, что в функции мы создали условие, в котором конкретно указали, если запрашивается категория с ID 10, то пост с ID 45 не выводить.

Далее мы цепляем созданный сценарий к событию pre_get_posts, которое, как я говорил выше, срабатывает непосредственно перед обращением WP_Query к БД и изменяем сам запрос.

Но что, если нам хочется убрать не один пост, а три и не только из категории, но и из архивов, со страниц меток и с главной страницы, т.е. скрыть посты полностью. Вуаля:

  function mayak_post_exclude($query){  	if ($query->is_main_query() or $query->is_archive())  	$query->set('post__not_in', array(45,57,98));  }  add_action('pre_get_posts','mayak_post_exclude');  

Ну хорошо, с постами вроде разобрались, но как быть, если стоит задача убрать рубрику полностью.

Как убрать посты дочерней рубрики из родительской

Мне довольно часто задавали такой вопрос. Ну вот видимо пришло время дать на него ответ.

Допустим, нам надо исключить все посты дочерней рубрики «Полезные свойства огурцов» с ID 18 из родительской рубрики «Салаты» с ID 10. Приступим:

	  function mayak_category_exclude($query){  	if ($query->is_category(10))   	$query->set ('cat', '-18');  }  add_action('pre_get_posts','mayak_category_exclude');	  

Надеюсь понятно, что для того, чтобы исключить рубрику, то ее ID в функции надо указывать с минусом. Остальное думаю уже не надо объяснять. Если надо убрать несколько дочерних рубрик, то указываем ID через запятую. Например:

	  function mayak_category_exclude($query){  	if ($query->is_category(10))   	$query->set ('cat', '-18,-22,-35');  }  add_action('pre_get_posts','mayak_category_exclude');  

Здесь важно понимать, что данная настройка WordPress касается только отображения контента и не в коем случаи не затрагивает меню рубрик. Если Вы хотите убрать рубрику из меню, то Вам надо обратиться к хуку-фильтру из функции wp_list_categories().

Как на главной странице вывести категорию

Давайте еще один пример рассмотрим, как на главной странице вывести цикл определенной категории:

  function mayak_category_home($query){  	if (is_home())   	$query->set ('cat', '10');  }	  add_action('pre_get_posts','mayak_category_home');	  

Теперь на главной странице, вместо основного цикла WordPress будет отображаться анонсы из указанной категории. Идем дальше

Разное количество постов на страницах

Речь конечно идет о количестве анонсов постов, хотя WP_Query получает посты полностью, ведь данный php-класс не занимается обрезкой текста или выводом цитаты, за это отвечают уже другие функции, а конкретно the_excerpt() и the_content().

Напомню, что количество постов на одной странице задается в админке (Настройки/Чтение/На страницах блога отображать не более).

Так вот, с помощью события pre_get_posts мы можем более тонко настроить отображение анонсов.

Например, на моем блоге на главной выводится десять анонсов, а на страницах категорий по пять, что конечно сказывается на общей нагрузке на сервер. Вот как это реализовывается:

  function mayak_paged( $query ) {  	if ($query->is_main_query())  		$query->set( 'posts_per_page', 10);  	if ($query->is_archive())  		$query->set( 'posts_per_page', 5);  }  add_action( 'pre_get_posts', 'mayak_paged');  

Можно вообще по хулиганить и вывести в разных категориях, разное количество анонсов:

  function mayak_paged( $query ) {  	if ($query->is_category(10))  		$query->set( 'posts_per_page', 7);  	if ($query->is_category(18))  		$query->set( 'posts_per_page', 5);  }  add_action( 'pre_get_posts', 'mayak_paged');  

В общем поле для экспериментов, не пахано, было бы желание его пахать!

До встречи!

С уважением, Виталий Кириллов

Источник