Can you filter posts by meta key with the getEntitityRecords selector?

(In hurry? Skip to the bottom for the code..)

So Gutenberg or the Block Editor uses the WordPress REST API when retrieving entity (e.g. postType>post and taxonomy>category) records (e.g. posts and terms).

For examples, for posts (post type of post), the route is /wp/v2/posts.

And for custom post types such as team, the default route is /wp/v2/team — you can change the team part via the rest_base parameter when you register the post type, which defaults to the post type slug.

But despite the routes are different, the default controller for posts (i.e. postType entity records) request is WP_REST_Posts_Controller, which you could change via the rest_controller_class parameter when registering the post type.

Having said that, you can see here for all the default parameters supported by that controller, and which one would supply as properties of the object in the third parameter of the wp.data.select( 'core' ).getEntityRecords():

wp.data.select( 'core' ).getEntityRecords( 'postType', 'post', {
  per_page: 2,
  orderby: 'title',
  ...
} );

Now if you look at those default parameters list, filtering the posts by metadata is (currently) not supported.

However, the good thing is that the default posts controller (WP_REST_Posts_Controller) has a hook you can use to modify the query/WP_Query parameters:

/**
 * Filters the query arguments for a request.
 *
 * Enables adding extra arguments or setting defaults for a post collection request.
 *
 * @since 4.7.0
 *
 * @link https://developer.wordpress.org/reference/classes/wp_query/
 *
 * @param array           $args    Key value array of query var to query value.
 * @param WP_REST_Request $request The request used.
 */
$args       = apply_filters( "rest_{$this->post_type}_query", $args, $request );

So in your case, you could make the meta query works like so:

add_filter( 'rest_team_query', function( $args, $request ){
    if ( $meta_key = $request->get_param( 'metaKey' ) ) {
        $args['meta_key'] = $meta_key;
        $args['meta_value'] = $request->get_param( 'metaValue' );
    }
    return $args;
}, 10, 2 );

That is just a basic example, but the main point is that you can use the rest_{post type slug}_query hook to filter the query.

And then in your getEntityRecords() call:

wp.data.select( 'core' ).getEntityRecords( 'postType', 'team', {
  // Default args.
  per_page: 2,
  orderby: 'title',

  // Custom args.
  metaKey: 'featured', // filter by metadata
  metaValue: '1' // not "true" unless the database value is exactly "true" (string)
} );

Leave a Comment