restrict_manage_posts
云策文档标注
概述
restrict_manage_posts 是一个 WordPress 动作钩子,在文章和页面列表表格的“筛选”按钮前触发,允许开发者添加自定义筛选控件。它主要用于扩展后台管理界面的筛选功能,支持基于分类法或自定义字段的过滤。
关键要点
- 触发时机:在文章列表和页面列表的“筛选”按钮前执行,用于添加额外的筛选选项。
- 参数:接受 $post_type(文章类型标识符)和 $which(位置标识符,如 'top'、'bottom' 或 'bar')。
- 用途:常用于为自定义文章类型添加分类法筛选下拉菜单,或基于元字段构建自定义筛选器。
- 关联操作:通常需要结合 parse_query 过滤器来修改查询,确保筛选生效。
- 版本历史:从 WordPress 2.1.0 引入,4.4.0 添加 $post_type 参数,4.6.0 添加 $which 参数。
代码示例
// 示例:添加自定义分类法筛选下拉菜单
add_action( 'restrict_manage_posts', 'add_admin_filters', 10, 1 );
public function add_admin_filters( $post_type ){
if( 'my_post_type' !== $post_type ){
return;
}
$taxonomies_slugs = array(
'my_taxonomy',
'my_other_taxonomy'
);
foreach( $taxonomies_slugs as $slug ){
$taxonomy = get_taxonomy( $slug );
$selected = isset( $_REQUEST[ $slug ] ) ? $_REQUEST[ $slug ] : '';
wp_dropdown_categories( array(
'show_option_all' => $taxonomy->labels->all_items,
'taxonomy' => $slug,
'name' => $slug,
'orderby' => 'name',
'value_field' => 'slug',
'selected' => $selected,
'hierarchical' => true,
) );
}
}注意事项
- 使用此钩子时,需确保筛选逻辑与 parse_query 过滤器配合,以正确修改查询参数。
- 注意参数 $which 的值,根据列表表格类型(如 WP_Posts_List_Table 或 WP_Media_List_Table)可能不同。
- 在添加自定义筛选器时,应检查 $post_type 以避免影响其他文章类型。
- 对于元字段筛选,可能需要直接操作数据库查询,并注意性能优化。
原文内容
Fires before the Filter button on the Posts and Pages list tables.
Description
The Filter button allows sorting by date and/or category on the Posts list table, and sorting by date on the Pages list table.
Parameters
$post_typestring-
The post type slug.
$whichstring-
The location of the extra table nav markup:
'top'or'bottom'for WP_Posts_List_Table,'bar'for WP_Media_List_Table.
Source
do_action( 'restrict_manage_posts', $this->screen->post_type, $which );
Skip to note 5 content
Roy Tanck
The example below eliminates the need for
parse_querywhen filtering based on taxonomy. It uses the taxonomy slug as URL parameter, just like WordPress does out of the box. The example adds filter dropdowns for two taxonomies, and allows for boolean AND filtering.add_action( 'restrict_manage_posts', 'add_admin_filters', 10, 1 ); public function add_admin_filters( $post_type ){ if( 'my_post_type' !== $post_type ){ return; } $taxonomies_slugs = array( 'my_taxonomy', 'my_other_taxonomy' ); // loop through the taxonomy filters array foreach( $taxonomies_slugs as $slug ){ $taxonomy = get_taxonomy( $slug ); $selected = ''; // if the current page is already filtered, get the selected term slug $selected = isset( $_REQUEST[ $slug ] ) ? $_REQUEST[ $slug ] : ''; // render a dropdown for this taxonomy's terms wp_dropdown_categories( array( 'show_option_all' => $taxonomy->labels->all_items, 'taxonomy' => $slug, 'name' => $slug, 'orderby' => 'name', 'value_field' => 'slug', 'selected' => $selected, 'hierarchical' => true, ) ); } }Skip to note 6 content
Aurovrata Venet
Use this hook to add a custom taxonomy filter for your post table,
add_action( 'restrict_manage_posts', 'my_post_type_filter', 10, 2 ); function my_post_type_filter( $post_type, $which ) { if ( 'my-post' !== $post_type ) { return; //check to make sure this is your cpt } $taxonomy_slug = 'my-post-type'; $taxonomy = get_taxonomy($taxonomy_slug); $selected = ''; $request_attr = 'my_type'; //this will show up in the url if ( isset( $_REQUEST[ $request_attr ] ) ) { $selected = $_REQUEST[ $request_attr ]; //in case the current page is already filtered } wp_dropdown_categories(array( 'show_option_all' => __("Show All {$taxonomy->label}"), 'taxonomy' => $taxonomy_slug, 'name' => $request_attr, 'orderby' => 'name', 'selected' => $selected, 'hierarchical' => true, 'depth' => 3, 'show_count' => true, // Show number of post in parent term 'hide_empty' => false, // Don't show posts w/o terms ) ); }Skip to note 7 content
Aurovrata Venet
To add a custom filter based on a meta field for example, you can build a custom dropdown filter,
add_action('restrict_manage_posts','location_filtering',10); function location_filtering($post_type){ if('my-custom-post' !== $post_type){ return; //filter your post } $selected = ''; $request_attr = 'my_loc'; if ( isset($_REQUEST[$request_attr]) ) { $selected = $_REQUEST[$request_attr]; } //get unique values of the meta field to filer by. $meta_key = 'my_custom_field_location'; global $wpdb; $result = $wpdb->get_col( $wpdb->prepare( " SELECT DISTINCT pm.meta_value FROM {$wpdb->postmeta} pm LEFT JOIN {$wpdb->posts} p ON p.ID = pm.post_id WHERE pm.meta_key = '%s' AND p.post_status IN ('publish', 'draft') ORDER BY pm.meta_value", $meta_key ) ); //build a custom dropdown list of values to filter by echo '<select id="my-loc" name="my_loc">'; echo '<option value="0">' . __( 'Show all locations', 'my-custom-domain' ) . ' </option>'; foreach($results as $location){ $select = ($org->ID == $selected) ? ' selected="selected"':''; echo '<option value="'.$location.'"'.$select.'>' . $location . ' </option>'; } echo '</select>'; }next we need to ensure the admin query returns the correct set of filtered posts by hooking onto the ‘parse_query’ filter,
add_filter( 'parse_query', 'filter_request_query' , 10); function filter_request_query($query){ //modify the query only if it admin and main query. if( !(is_admin() AND $query->is_main_query()) ){ return $query; } //we want to modify the query for the targeted custom post and filter option if( !('my-custom-post' === $query->query['post_type'] AND isset($_REQUEST['my_loc']) ) ){ return $query; } //for the default value of our filter no modification is required if(0 == $_REQUEST['my_loc']){ return $query; } //modify the query_vars. $query->query_vars = array(array( 'field' => 'my_custom_field_location', 'value' => $_REQUEST['my_loc'], 'compare' => '=', 'type' => 'CHAR' )); return $query; }To build more complex meta field queries, lookup the documentation for the
WP_Meta_Queryobject.Skip to note 8 content
Aurovrata Venet
Use this hook to add a custom taxonomy filter for your post table,
add_action('restrict_manage_posts','my_post_type_filter',10,2); function my_post_type_filter($post_type, $which){ if('my-post' !== $post_type){ return; //check to make sure this is your cpt } $taxonomy_slug = 'my-post-type'; $taxonomy = get_taxonomy($taxonomy_slug); $selected = ''; $request_attr = 'my_type'; //this will show up in the url if ( isset($_REQUEST[$request_attr] ) ) { $selected = $_REQUEST[$request_attr]; //in case the current page is already filtered } wp_dropdown_categories(array( 'show_option_all' => __("Show All {$taxonomy->label}"), 'taxonomy' => $taxonomy_slug, 'name' => $request_attr, 'orderby' => 'name', 'selected' => $selected, 'hierarchical' => true, 'depth' => 3, 'show_count' => true, // Show number of post in parent term 'hide_empty' => false, // Don't show posts w/o terms )); }to ensure the post table is correctly filtered, the post query needs to be modified to filter the selected term. This is done by hooking the
'parse_query'filter,add_filter( 'parse_query', 'filter_request_query' , 10); function filter_request_query($query){ //modify the query only if it is admin and main query. if( !(is_admin() AND $query->is_main_query()) ){ return $query; } //we want to modify the query for the targeted custom post. if( 'my-post' !== $query->query['post_type'] ){ return $query; } //type filter if( isset($_REQUEST['my_type']) && 0 != $_REQUEST['my_type']){ $term = $_REQUEST['my_type']; $taxonomy_slug = 'my-post-type'; $query->query_vars['tax_query'] = array( array( 'taxonomy' => $taxonomy_slug, 'field' => 'ID', 'terms' => array($term) ) ); } return $query; }