I hope you can help me see what’s wrong here! I am finding that when I create new posts of a custom post type with a custom meta key, unless I actively click that particular meta option when creating the post, the post doesn’t appear in meta_query filters. If I just create a new post of that type but don’t click anything, so the value is left as the registered default, it’s ignored.
I have a custom post type initialised on the “init” hook like so:
add_action( 'init', array( $this, 'create_post_type_and_meta_fields' ) );
In that function, as well as creating the post type itself, I am registering meta fields like this:
$fields = array(
array(
'field_name' => 'start_date',
'field_type' => 'string',
'default' => '',
),
array(
'field_name' => 'location',
'field_type' => 'string',
'default' => 'in-person',
),
);
foreach ( $fields as $field ) {
register_post_meta(
$post_type = 'event',
$meta_key = 'event_' . $field[ 'field_name' ],
$args = array(
'show_in_rest' => true,
'single' => true,
'type' => $field[ 'field_type' ],
'default' => $field[ 'default' ],
'auth_callback' => function() {
return current_user_can( 'edit_events' );
}
)
);
}
Then in the admin I am filtering for these meta values like this:
public function process_filters( $query ) {
global $pagenow;
$post_type = $_GET[ 'post_type' ] ?? 'post';
if ( is_admin() && $post_type == 'event' && $pagenow == 'edit.php' ) {
// Get the meta query so far
$meta_query = $query->get( 'meta_query' );
// If it's empty, start a new one
if ( empty( $meta_query ) ) {
$meta_query = array();
}
// If applicable, add a filter for location to our meta query
if ( !empty( $_GET[ 'filter_location' ] ) ) {
$meta_query[] = array(
'relation' => 'OR',
array(
'key' => 'event_location',
'value' => $_GET[ 'filter_location' ],
'compare' => '='
),
array(
'key' => 'event_location',
'value' => 'hybrid',
'compare' => '='
)
);
}
// Save the updated meta query
$query->set( 'meta_query', $meta_query );
}
return $query;
}
These filters work perfectly when $_GET[ 'filter_location' ]
matches an option I’ve selected for the post, but do not match anything when the post just has that value as the default.
However, outputting get_post_meta( $post_id, 'event_location', true )
for a post where I didn’t choose an option DOES return the default in-person
, as it should.
Any ideas? I’m afraid it’s one of those!
Tim Wakeling is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.