pre_get_posts хук-подіяWP 2.0.0

Дозволяє змінити запит WP_Query . Спрацьовує перед запитом.

Ця подія дозволяє змінювати об’єкт $wp_query. Об’єкт передається в хук за посиланням – це означає, що будь-які дії над змінною $query всередині функції впливатимуть на основний об’єкт WP_Query . Для цього хука не треба повертати жодних даних.

ВАЖЛИВО! Ця подія спрацьовує для кожного запиту WP_Query:

  • основний запит
  • додатковий запит
  • запит до адмін-панелі
  • запити у віджетах
  • і т.д.

Тому переконайтеся, що змінюєте саме потрібний запит, для цього перед зміною запиту використовуйте всілякі Умовні теги , щоб точно обмежити зміну (див. приклади).

Часті функції всередині цього хука:

  • $query->is_main_query() — змінимо лише основний запит WP.
  • is_admin() — змінимо запити лише до адмін панелі.
  • get_queried_object() – дані поточного запиту (поточної сторінки).

Використання get_queried_object() всередині цього хука, потрібно здійснювати перевіркою $query->is_author :

add_action( 'pre_get_posts', 'function_name');
function function_name( $query ){

	if( $query->is_author )
		$qo = $query->queried_object();
	else
		$qo = get_queried_object();
}

Схоже, що це баг при якому для сторінки автора занадто рано використовувати get_queried_object() до обробки даних запиту. Саме при обробці встановлюється властивість $wp_query->query_vars[‘author’] на основі якого встановлюється об’єкт користувача на сторінці користувача функції get_queried_object() . А якщо цих даних немає, то і поточний об’єкт користувача отримати не вдасться.

Створив тикет за цим багом: https://core.trac.wordpress.org/ticket/51829

Використання

add_action( 'pre_get_posts', 'wp_kama_pre_get_posts_action');

/**
 * Function for `pre_get_posts` action-hook.
 *
 * @param WP_Query $query WP_Query instance (passed by reference).
 *
 * @return void
 */
function wp_kama_pre_get_posts_action( $query ){

	// action...
}
$query
( WP_Query )
Об’єкт WP_Query.

нотатки

Аргумент передається за посиланням

Об’єкт $query надається за посиланням, тому немає необхідності визначати глобальну змінну. Будь-які зміни $query усередині функції впливають відразу на оригінальний об’єкт.

Запити постійних сторінок

pre_get_posts не можна використовувати для зміни запитів, пов’язаних із постійними сторінками, тому що ‘is_page’, ‘is_singular’, ‘pagename’ та інші параметри (залежні до ЧПК) вже встановлені в об’єкті. Рекомендовано використовувати новий WP_Query у шаблоні постійної сторінки, щоб змінити запит.

Визначення потрібного запиту

При використанні pre_get_posts потрібно точно визначити, в який конкретно запит ви вносите зміни. Корисний метод для цього: умовними тегами . Щоб змінювати запит лише для сторінок, які вам потрібні.

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

Використання в адмін-панелі

Цю подію можна також використовувати для зміни запитів до адмін-панелі. У таких випадках переконайтеся, що внесені зміни працюватимуть на сторінці виводу записів. Наприклад, перевірка is_post_type_archive(‘movie’) (змінюємо запит для лицьової частини для записів типу movie), змінить також запит на сторінки edit.php?post_type=movie. Щоб цього не сталося, потрібно використати ще перевірку ! is_admin().

Увага! Умовні теги

Ця подія спрацьовує до того, як об’єкт WP_Query повністю визначиться. Тому деякі умовні теги, що спираються на дані WP_Query, ще не працюють. Наприклад, is_home() буде працювати. Тому краще працювати з даними об’єкта безпосередньо, наприклад $query->is_search .

Весь список властивостей, які можна використовувати замість умовного тега:

$query->is_404
$query->is_admin
$query->is_archive
$query->is_attachment
$query->is_author
$query->is_category
$query->is_comments_popup
$query->is_comment_feed
$query->is_date
$query->is_day
$query->is_feed
$query->is_home
$query->is_month
$query->is_page
$query->is_paged
$query->is_posts_page
$query->is_post_type_archive
$query->is_preview
$query->is_robots
$query->is_search
$query->is_single
$query->is_singular
$query->is_tag
$query->is_tax
$query->is_time
$query->is_trackback
$query->is_year

// функції
$query->is_front_page()
$query->is_main_query()

Решту умовних тегів потрібно замінити перевіркою або методом класу. Наприклад, is_front_page()потрібно замінити на такий метод:

if( $query->is_front_page() ){
	// це front_page
}

або на таку перевірку:

if(
	$query->is_home
	||
	( $query->get('page_id') == get_option('page_on_front') )
) {
	// це front_page
}

$query->is_main_query() .

Відступи та пагінація

Використання аргументу offsetу будь-якому запиті може зламати пагінацію. Тому, якщо ви використовуєте offset, вам потрібно змінити запит для всіх сторінок пагінації, спираючись на початковий відступ (offset). Докладніше про це я писав у цій статті: Як використовувати параметр offset не ламаючи пагінацію .

Приклади

1

#1 Включення довільного типу записів до результатів пошуку

Включати пошук довільний тип запису чи ні, встановлюється при реєстрації типу запису, в аргументах функції register_post_type() : аргумент public=true додає в результат пошуку довільний тип запису.

Якщо довільний тип не включений у пошук, але потрібно щоб він брав участь у пошуку, то використовуйте такий код, аналог попереднього:

add_action( 'pre_get_posts', 'get_posts_search_filter');
function get_posts_search_filter( $query ){

	if ( ! is_admin() && $query->is_main_query() && $query->is_search ) {
		$query->set( 'post_type', [ 'post', 'movie' ] );
	}
}

0

#2 Виняток категорій на головній

Цей приклад показує, як прибрати пости із зазначених категорій з висновку на головній сторінці блогу. Наприклад, у нас є 2 категорії з ID 1 та 1347, які нам не потрібно показувати на головній. Щоб виключити ці категорії із запиту, використовуйте такий код у плагіні або темі:

add_action( 'pre_get_posts', 'exclude_category' );
function exclude_category( $query ) {
	if ( $query->is_front_page() && $query->is_main_query() ) {
		$query->set('cat', '-1,-1347');
	}
}

0

#3 Виключення постійних сторінок із результатів пошуку

Коли користувачі вашого сайту що-небудь шукають, часто в результатах пошуку можуть траплятися постійні сторінки, які в принципі зовсім не потрібні в результатах пошуку, і які можна виключити з пошуку назовсім. Використовуйте хук pre_get_posts, щоб виключити з результатів пошуку постійних сторінок:

add_action( 'pre_get_posts', 'search_filter');
function search_filter( $query ){

	if( ! is_admin() && $query->is_main_query() && $query->is_search ){
		$query->set('post_type', 'post');
	}
}

0

#4 Зміна кількості постів, що виводяться на сторінці

У WordPress є глобальне налаштування, яке враховує скільки записів показувати на сторінці – posts_per_page . Найкраще змінювати цей параметр до основного запиту з метою економії ресурсів, щоб не робити повторних запит. Так, ми можемо використовувати хук-дія pre_get_posts , щоб змінити кількість записів, що виводяться на сторінці.

Цей приклад показує, як перезаписати параметр posts_per_page для сторінки архівів довільного типу запису movie :

add_action( 'pre_get_posts', 'hwl_home_pagesize', 1);
function hwl_home_pagesize( $query ) {

	// Виходимо, якщо це адмін-панель або основний запит.
	if( is_admin() || ! $query->is_main_query() )
		return;

	if( is_home() ){
		// Виводимо лише 1 пост на головній сторінці
		$query->set( 'posts_per_page', 1);
	}

	// Виводимо 50 записів, якщо це архів типу запису 'movie'
	if( $query->is_post_type_archive('movie') ){
		$query->set( 'posts_per_page', 50);
	}
}

0

#5 Приклад об’єкта WP_Query

Для того, щоб швидко розібратися як і що використовувати нижче приклад об’єкта WP_Query (global $wp_query ), який передається в хук за посиланням (&$query):

WP_Query Object
(
	[query_vars] => Array
		(
			[page] => 0
			[pagename] => s
			[error] =>
			[m] =>
			[p] => 0
			[post_parent] =>
			[subpost] =>
			[subpost_id] =>
			[attachment] =>
			[attachment_id] => 0
			[name] => s
			[static] =>
			[page_id] => 0
			[second] =>
			[minute] =>
			[hour] =>
			[day] => 0
			[monthnum] => 0
			[year] => 0
			[w] => 0
			[category_name] =>
			[tag] =>
			[cat] =>
			[tag_id] =>
			[author] =>
			[author_name] =>
			[feed] =>
			[tb] =>
			[paged] => 0
			[comments_popup] =>
			[meta_key] =>
			[meta_value] =>
			[preview] =>
			[s] =>
			[sentence] =>
			[fields] =>
			[menu_order] =>
			[category__in] => Array
				(
				)

			[category__not_in] => Array
				(
				)

			[category__and] => Array
				(
				)

			[post__in] => Array
				(
				)

			[post__not_in] => Array
				(
				)

			[tag__in] => Array
				(
				)

			[tag__not_in] => Array
				(
				)

			[tag__and] => Array
				(
				)

			[tag_slug__in] => Array
				(
				)

			[tag_slug__and] => Array
				(
				)

			[post_parent__in] => Array
				(
				)

			[post_parent__not_in] => Array
				(
				)

			[author__in] => Array
				(
				)

			[author__not_in] => Array
				(
				)

			[ignore_sticky_posts] =>
			[suppress_filters] =>
			[cache_results] =>
			[update_post_term_cache] => 1
			[update_post_meta_cache] => 1
			[post_type] =>
			[posts_per_page] => 10
			[nopaging] =>
			[comments_per_page] => 10
			[no_found_rows] =>
			[order] => DESC
		)

	[tax_query] =>
	[meta_query] => WP_Meta_Query Object
		(
			[queries] => Array
				(
				)

			[relation] =>
		)

	[date_query] =>
	[post_count] => 1
	[current_post] => -1
	[in_the_loop] =>
	[comment_count] => 0
	[current_comment] => -1
	[found_posts] => 1
	[max_num_pages] => 0
	[max_num_comment_pages] => 0
	[is_single] =>
	[is_preview] =>
	[is_page] => 1
	[is_archive] =>
	[is_date] =>
	[is_year] =>
	[is_month] =>
	[is_day] =>
	[is_time] =>
	[is_author] =>
	[is_category] =>
	[is_tag] =>
	[is_tax] =>
	[is_search] =>
	[is_feed] =>
	[is_comment_feed] =>
	[is_trackback] =>
	[is_home] =>
	[is_404] =>
	[is_comments_popup] =>
	[is_paged] =>
	[is_admin] =>
	[is_attachment] =>
	[is_singular] => 1
	[is_robots] =>
	[is_posts_page] =>
	[is_post_type_archive] =>
	[query_vars_hash] => c248b13e251e8fba33892e0bd7a5bd98
	[query_vars_changed] =>
	[thumbnails_cached] =>
	[stopwords:WP_Query:private] =>
	[query] => Array
		(
			[page] =>
			[pagename] => s
		)

	[queried_object] => WP_Post Object
		(
			[ID] => 19
			[post_author] => 1
			[post_date] => 2010-04-01 20:09:20
			[post_date_gmt] => 2010-04-01 16:09:20
			[post_content] =>
			[post_title] => Сторінка для виконання
			[post_excerpt] =>
			[post_status] => private
			[comment_status] => open
			[ping_status] => closed
			[post_password] =>
			[post_name] => s
			[to_ping] =>
			[pinged] =>
			[post_modified] => 2011-04-25 17:44:42
			[post_modified_gmt] => 2011-04-25 13:44:42
			[post_content_filtered] =>
			[post_parent] => 0
			[guid] => http://example.com/s
			[menu_order] => 0
			[post_type] => page
			[post_mime_type] =>
			[comment_count] => 0
			[filter] => raw
		)

	[queried_object_id] => 19
	[request] => SELECT wp_posts.* FROM wp_posts WHERE 1=1
				 AND (wp_posts.ID = '19') AND wp_posts.post_type = 'page'
				 ORDER BY wp_posts.post_date DESC
	[posts] => Array
		(
			[0] => WP_Post Object
				(
					[ID] => 19
					[post_author] => 1
					[post_date] => 2010-04-01 20:09:20
					[post_date_gmt] => 2010-04-01 16:09:20
					[post_content] =>
					[post_title] => Сторінка для виконання
					[post_excerpt] =>
					[post_status] => private
					[comment_status] => open
					[ping_status] => closed
					[post_password] =>
					[post_name] => s
					[to_ping] =>
					[pinged] =>
					[post_modified] => 2011-04-25 17:44:42
					[post_modified_gmt] => 2011-04-25 13:44:42
					[post_content_filtered] =>
					[post_parent] => 0
					[guid] => http://example.com/s
					[menu_order] => 0
					[post_type] => page
					[post_mime_type] =>
					[comment_count] => 0
					[filter] => raw
				)

		)

	[post] => WP_Post Object
		(
			[ID] => 19
			[post_author] => 1
			[post_date] => 2010-04-01 20:09:20
			[post_date_gmt] => 2010-04-01 16:09:20
			[post_content] =>
			[post_title] => Сторінка для виконання
			[post_excerpt] =>
			[post_status] => private
			[comment_status] => open
			[ping_status] => closed
			[post_password] =>
			[post_name] => s
			[to_ping] =>
			[pinged] =>
			[post_modified] => 2011-04-25 17:44:42
			[post_modified_gmt] => 2011-04-25 13:44:42
			[post_content_filtered] =>
			[post_parent] => 0
			[guid] => http://example.com/s
			[menu_order] => 0
			[post_type] => page
			[post_mime_type] =>
			[comment_count] => 0
			[filter] => raw
		)

)

список змін

З версії 2.0.0Введено.

Де викликається хук

Залишити відповідь

Ваша e-mail адреса не оприлюднюватиметься. Обов’язкові поля позначені *