First couple of handy helper functions,
function my_custom_post_type() {
return 'post'; // edit this
}
function custom_field_status_metakey() {
return 'status';
}
function custom_field_status_options() {
return array(
'' => __( 'All statuses', 'textdomain' ), // edit text domains
'open' => __( 'Open', 'textdomain' ),
'closed' => __( 'Closed', 'textdomain' ),
);
}
Add your custom column to the post list with manage_{post_type}_posts_columns
and manage_{post_type}_posts_custom_column
. Update the {post_type}
parts below to match your custom post type.
add_filter( 'manage_{post_type}_posts_columns', 'set_custom_edit_book_columns' );
function set_custom_edit_book_columns($columns) {
$columns[custom_field_status_metakey()] = __( 'Status', 'textdomain' ); // reorder columns, if needed
return $columns;
}
add_action( 'manage_{post_type}_posts_custom_column' , 'custom_book_column', 10, 2 );
function custom_book_column( $column, $post_id ) {
$key = custom_field_status_metakey();
if ( $key === $column ) {
echo get_post_meta( $post_id, $key, true );
}
}
Add a filter select to the posts lists with restrict_manage_posts
.
add_action( 'restrict_manage_posts', 'filter_post_by_custom_field_status' , 10, 2);
function filter_post_by_custom_field_status( $post_type, $which ) {
if ( my_custom_post_type() === $post_type ) {
$meta_key = custom_field_status_metakey();
$options = custom_field_status_options();
echo "<select name="{$meta_key}" id='{$meta_key}' class="postform">";
foreach ( $options as $value => $name ) {
printf(
'<option value="%1$s" %2$s>%3$s</option>',
esc_attr($value),
( ( isset( $_GET[$meta_key] ) && ( $_GET[$meta_key] === $value ) ) ? ' selected="selected"' : '' ),
esc_html($name)
);
}
echo '</select>';
}
}
Use parse_query
to filter posts based on the selected status value.
add_filter( 'parse_query', 'filter_parse_query_custom_field_status' );
function filter_parse_query_custom_field_status( $query ){
global $pagenow;
$meta_key = custom_field_status_metakey();
$valid_status = array_keys(custom_field_status_options());
$status = (! empty($_GET[$meta_key]) && in_array($_GET[$meta_key],$valid_status)) ? $_GET[$meta_key] : '';
if ( is_admin() && 'edit.php' === $pagenow && isset($_GET['post_type']) && my_custom_post_type() === $_GET['post_type'] && $status ) {
$query->query_vars['meta_key'] = $meta_key;
$query->query_vars['meta_value'] = $status;
}
}
Toss the codes above to your functions.php
and modify as needed.
Or register a custom taxonomy for your post type and you’ll get the above kind of automatically. Plus using a custom taxonomy instead of meta can make post queries more efficient. More on that here https://tomjn.com/2016/12/05/post-meta-abuse/ by WPSE member Tom J Nowell.