restrict_manage_posts
Срабатывает перед кнопкой «Фильтр» в таблице записей админки. Позволяет добавить поля для фильтрации записей, страниц и произвольных типов записей.
Хук также работает в медиатеке в режиме списка.
Обработчик должен выводить 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. |
Где вызывается хук
do_action( 'restrict_manage_posts', $this->screen->post_type, $which );
do_action( 'restrict_manage_posts', $this->screen->post_type, $which );
