WordPress как на ладони
wordpress jino

posts_where хук-фильтр . WP 1.5.2

Позволяет изменять WHERE часть SQL запроса связанного с получением записей (WP_Query).

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

Фильтр posts_where срабатывает до установки запроса пагинации, поэтому фильтр нужно использовать, когда изменения никак не связаны с пагинацией. Чтобы изменения влияли и на пагинацию, нужно использовать аналогичный фильтр posts_where_paged, который срабатывает после установки запроса пагинации.

Перед тем, как изменять запрос, установите условия if, чтобы точно определить страницу или событие, когда запрос должен изменяться. Фильтр срабатывает всякий раз, когда вызывается WP_Query и запрос может быть изменен там, где это совершенно не нужно. Это может стать проблемой, изменив запрос для одной страницы, он будет меняться везде.

Использование

function filter_function_name_11( $where ) {
	// Фильтр...

	return $where;
}
add_filter( 'posts_where', 'filter_function_name_11' );
$where(строка)
Часть текущего SQL запроса. Например: WHERE post_status = 'publish' AND post_author = '1'.

Примеры

#1 Ограничим выборку постов в админ-панели

Предположим, у нас есть тип записи book с прикрепленной к нему таксономией author (авторы книг). Мы использовали хук-действие restrict_manage_posts, через который создали выпадающий список авторов (термины таксономии). Теперь, при выборе из списка автора и нажатии на кнопку "фильтровать", нам нужно получить записи (книги) этого автора. Имя автора в этом случае будет добавлено в $_GET переменную author_restrict_posts. Учитывая эту переменную и используя posts_where, мы можем изменить запрос:

add_filter( 'posts_where' , 'posts_where' );

function posts_where( $where ) {

	if( is_admin() ) {
		global $wpdb;

		if ( 
			isset( $_GET['author_restrict_posts'] ) && 
			!empty( $_GET['author_restrict_posts'] ) && 
			intval( $_GET['author_restrict_posts'] ) != 0 
		) {
			$author = intval( $_GET['author_restrict_posts'] );

			$where .= " AND ID IN (SELECT object_id FROM {$wpdb->term_relationships} WHERE term_taxonomy_id=$author )";
		}
	}
	return $where;
}

Заметки

#1 suppress_filters

Если нужно отключить работу всех фильтров в WP_Query связанных с изменением SQL запроса, то определите параметр suppress_filters=true. Тогда никакие фильтры не будут срабатывать и WP_Query будет работать "мимо" фильтров:

posts_where
posts_join
posts_where_paged
posts_groupby
posts_join_paged
posts_distinct
post_limits
posts_fields
posts_request
posts_results
the_posts`
 и т.д.

По умолчанию, в функции получения постов get_posts(), suppress_filters = true и она не чувствительна к изменениям запросов через фильтры. Смотрите пример:

<?php
// Функция которая изменяет запрос
function useless_condition ( $where ) { return $where . ' AND 1=1 '; }

// Прикрепляем функцию к фильтру posts_where
add_filter( 'posts_where' , 'useless_condition' );

// Получаем посты и делаем так, чтобы наши фильтры сработали
// Для этого указываем параметр suppress_filters, 
// по умолчанию в get_posts он true
$posts = get_posts( array( 'suppress_filters' => FALSE ) );
?>

Связи хука

Используется в: WP_Query::get_posts()

Остальные хуки из: WP_Query::get_posts():

Фрагменты кода хука posts_where

Фрагмент из: wp-includes/class-wp-query.php VER 4.9.1
...
		}

		/*
		 * Apply filters on where and join prior to paging so that any
		 * manipulations to them are reflected in the paging by day queries.
		 */
		if ( !$q['suppress_filters'] ) {
			/**
			 * Filters the WHERE clause of the query.
			 *
			 * @since 1.5.0
			 *
			 * @param string   $where The WHERE clause of the query.
			 * @param WP_Query $this The WP_Query instance (passed by reference).
			 */
			$where = apply_filters_ref_array( 'posts_where', array( $where, &$this ) );

			/**
			 * Filters the JOIN clause of the query.
			 *
			 * @since 1.5.0
			 *
			 * @param string   $join  The JOIN clause of the query.
			 * @param WP_Query $this The WP_Query instance (passed by reference).
			 */
			$join = apply_filters_ref_array( 'posts_join', array( $join, &$this ) );
		}

		// Paging
		if ( empty($q['nopaging']) && !$this->is_singular ) {
			$page = absint($q['paged']);
...
posts_where 2 комментария
  • Людмила

    А для комментариев аналогичной штуки нету?
    Мне нужно сделать возможность сортировать комментарии в админке по дополнительному признаку. Сделала выпадающий список с помощью restrict_manage_comments . Теперь надо как-то модифицировать $cwhere в зависимости от того, что выбрано.

    1
    Ответить1.4 года назад #
    • Kama4697

      Там комменты строятся на базе функции get_comments(), которая в свою очередь работает на базе класса WP_Comment_Query, а значит вам нужны хуки из этого класса... Вот 2, которые вам подходят:

      Один

      Фильтрует сам SQL запрос по частям. Аналогичный пример для записей, смотрите в статье про колонки

              /**
      		 * Filter the comment query clauses.
      		 *
      		 * @since 3.1.0
      		 *
      		 * @param array            $pieces A compacted array of comment query clauses.
      		 * @param WP_Comment_Query &$this  Current instance of WP_Comment_Query, passed by reference.
      		 */
      		$clauses = apply_filters_ref_array( 'comments_clauses', array( compact( $pieces ), &$this ) );

      Два

      Изменяет передаваемые параметры, аналогичный пример для записей смотрите в описании хука pre_get_posts

              /**
      		 * Fires before comments are retrieved.
      		 *
      		 * @since 3.1.0
      		 *
      		 * @param WP_Comment_Query &$this Current instance of WP_Comment_Query, passed by reference.
      		 */
      		do_action_ref_array( 'pre_get_comments', array( &$this ) );
      3
      Ответить1.4 года назад #

Здравствуйте, !

Ваш комментарий