restrict_manage_posts │ хук-событие │ WP 2.1.0

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

Хук также работает в медиатеке в режиме списка.

Обработчик должен выводить HTML на экран, например через echo. Поля будут находится внутри существующей формы: создавать свою <form> не нужно. После нажатия «Фильтр» значения передаются в URL.

Хук только выводит элементы интерфейса. Чтобы произвольное поле влияло на выборку, нужно отдельно измените запрос через pre_get_posts или parse_query.

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

Для добавления элементов после блока действий, в том числе снизу таблицы, используйте manage_posts_extra_tablenav.

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

add_action( 'restrict_manage_posts', 'wp_kama_restrict_manage_posts_action', 10, 2 );

/**
 * Function for `restrict_manage_posts` action-hook.
 * 
 * @param string $post_type The post type slug.
 * @param string $which     The location of the extra table nav markup: 'top' or 'bottom' for
 *                          WP_Posts_List_Table, 'bar' for WP_Media_List_Table.
 *
 * @return void
 */
function wp_kama_restrict_manage_posts_action( $post_type, $which ){
	// action...
}
$post_type(строка)
Название типа записи: post, page, attachment или кастомный тип. Проверяйте его, чтобы выводить поля только на нужном экране.
$which(строка)

Расположение панели, в которой вызывается хук:

  • top - верхняя панель таблицы записей.
  • bar - панель фильтров медиатеки в режиме списка.

В документации также указано bottom, однако в текущем коде (WP 7.1) WP_Posts_List_Table::extra_tablenav() вызов этого хука находится внутри условия 'top' === $which. Поэтому снизу стандартной таблицы записей он не срабатывает.

Примеры

#1 Фильтры по произвольным таксономиям

Добавим два списка для типа записи book: по жанру genre и языку book_language. Тип записи и таксономии должны быть заранее зарегистрированы, таксономии связаны с book, а их query_var включён.

add_action( 'restrict_manage_posts', 'myplugin_book_taxonomy_filters', 10, 2 );

function myplugin_book_taxonomy_filters( $post_type, $which ) {

	if ( 'book' !== $post_type || 'top' !== $which ) {
		return;
	}

	foreach ( [ 'genre', 'book_language' ] as $taxonomy_name ) {
		$taxonomy = get_taxonomy( $taxonomy_name );

		if ( ! $taxonomy || ! $taxonomy->query_var ) {
			continue;
		}

		$name     = $taxonomy->query_var;
		$selected = sanitize_text_field( wp_unslash( $_GET[ $name ] ?? '' ) ) ?: '';

		wp_dropdown_categories( [
			'taxonomy'        => $taxonomy_name,
			'name'            => $name,
			'id'              => "filter-{$name}",
			'show_option_all' => $taxonomy->labels->all_items,
			'value_field'     => 'slug',
			'selected'        => $selected,
			'orderby'         => 'name',
			'hierarchical'    => true,
			'hide_empty'      => false,
		] );
	}
}

Здесь name берётся из $taxonomy->query_var: он может отличаться от названия таксономии.

#2 Фильтр по метаполю

Добавим фильтр книг по метаполю reading_status, в котором хранятся значения planned или finished.

add_action( 'restrict_manage_posts', 'myplugin_book_status_filter', 10, 2 );
add_action( 'pre_get_posts', 'myplugin_filter_books_by_status' );

function myplugin_book_status_filter( $post_type, $which ) {

	if ( 'book' !== $post_type || 'top' !== $which ) {
		return;
	}

	$value = sanitize_key( wp_unslash( $_GET['book_status'] ?? '' ) ) ?: '';

	$options = [
		''         => __( 'Все статусы чтения', 'myplugin' ),
		'planned'  => __( 'В планах', 'myplugin' ),
		'finished' => __( 'Прочитано', 'myplugin' ),
	];

	$options = [];

	foreach ( $options as $key => $label ) {
		$options[] = sprintf(
			'<option value="%s"%s>%s</option>',
			esc_attr( $key ),
			selected( $value, $key, false ),
			esc_html( $label )
		);
	}

	echo '<select name="book_status" id="book-status">' . implode( "\n", $options ) . '</select>';
}

function myplugin_filter_books_by_status( $query ) {

	if (
		! is_admin()
		|| 'edit.php' !== ( $GLOBALS['pagenow'] ?? '' )
		|| ! $query->is_main_query()
		|| 'book' !== $query->get( 'post_type' )
	) {
		return;
	}

	$value = sanitize_key( wp_unslash( $_GET['book_status'] ?? '' ) ) ?: '';

	if ( ! in_array( $value, [ 'planned', 'finished' ], true ) ) {
		return;
	}

	$meta_query = [
		'relation' => 'AND',
		[
			'key'   => 'reading_status',
			'value' => $value,
		],
	];

	$existing = $query->get( 'meta_query' );
	if ( $existing ) {
		$meta_query[] = $existing;
	}

	$query->set( 'meta_query', $meta_query );
}

Существующий meta_query сохраняется отдельной группой, поэтому его внутренние связи AND/OR не меняются. Подробнее об условиях метаполей: WP_Meta_Query{}.

Если варианты ($options) заранее неизвестны, список можно сформировать из уникальных значений метаполя:

global $wpdb;

$values = $wpdb->get_col( $wpdb->prepare("
	SELECT DISTINCT pm.meta_value
		FROM {$wpdb->postmeta} AS pm
		INNER JOIN {$wpdb->posts} AS p ON (p.ID = pm.post_id)
	WHERE pm.meta_key = %s
		AND p.post_type = %s
		AND p.post_status IN ( 'publish', 'draft' )
		AND pm.meta_value != ''
	ORDER BY pm.meta_value ASC",
	'reading_status',
	'book'
) );

$options = [
	'' => __( 'Все статусы чтения', 'myplugin' ),
];

foreach ( $values as $value ) {
	$options[ $value ] = $value;
}

Список изменений

С версии 2.1.0 Введена.
С версии 4.4.0 The $post_type parameter was added.
С версии 4.6.0 The $which parameter was added.

Где вызывается хук

WP_Posts_List_Table::extra_tablenav()
restrict_manage_posts
WP_Media_List_Table::extra_tablenav()
restrict_manage_posts
wp-admin/includes/class-wp-posts-list-table.php 593
do_action( 'restrict_manage_posts', $this->screen->post_type, $which );
wp-admin/includes/class-wp-media-list-table.php 243
do_action( 'restrict_manage_posts', $this->screen->post_type, $which );

Где используется хук в WordPress

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