1

This is my first time working with REST, and I'm having difficulty getting posts by a meta key. I've added the meta keys I need using register_meta, and running a request on /wp-json/wp/v2/products, the output does contain my custom fields.

I know I can add ?slug={some slug}, or ?id={some id} to retrieve posts by those values, and that works fine in testing. But I can't figure out how to parse the custom fields because they're nested in the JSON data under a "meta" listing.

After Googling around for about an hour to no avail, I just started guessing at what I was supposed to do. I've tried a number of things like ?brand_name=test, ?meta[brand_name]=test, and ?[meta]brand_name=test, but none of those seem to do anything.

I'm sure I'm missing something obvious; I'd really appreciate some help. An example of my JSON data is below.

[
   {  
      "id":5,
      "date":"2017-05-04T10:36:10",
      "date_gmt":"2017-05-04T15:36:10",
      "guid":{  
         "rendered":"http:\/\/products.example.localhost\/?post_type=product&p=5"
      },
      "modified":"2017-05-09T13:41:12",
      "modified_gmt":"2017-05-09T18:41:12",
      "slug":"12545xa573",
      "status":"publish",
      "type":"product",
      "link":"http:\/\/products.example.localhost\/products\/12545xa573\/",
      "title":{  
         "rendered":"12545XA573"
      },
      "excerpt":{  
         "rendered":"",
         "protected":false
      },
      "author":1,
      "featured_media":32,
      "comment_status":"open",
      "ping_status":"open",
      "template":"",
      "format":"standard",
      "meta":{  
         "brand_name":"test",
         "sku":"12545XA573",
         "unit_of_measure":"FT, 1\/8, 1\/16",
         "length":"3.20 in"
      },
      "_links":{  
         "self":[  
            {  
               "href":"http:\/\/products.example.localhost\/wp-json\/wp\/v2\/products\/5"
            }
         ],
         "collection":[  
            {  
               "href":"http:\/\/products.example.localhost\/wp-json\/wp\/v2\/products"
            }
         ],
         "about":[  
            {  
               "href":"http:\/\/products.example.localhost\/wp-json\/wp\/v2\/types\/product"
            }
         ],
         "author":[  
            {  
               "embeddable":true,
               "href":"http:\/\/products.example.localhost\/wp-json\/wp\/v2\/users\/1"
            }
         ],
         "replies":[  
            {  
               "embeddable":true,
               "href":"http:\/\/products.example.localhost\/wp-json\/wp\/v2\/comments?post=5"
            }
         ],
         "version-history":[  
            {  
               "href":"http:\/\/products.example.localhost\/wp-json\/wp\/v2\/products\/5\/revisions"
            }
         ],
         "wp:featuredmedia":[  
            {  
               "embeddable":true,
               "href":"http:\/\/products.example.localhost\/wp-json\/wp\/v2\/media\/32"
            }
         ],
         "wp:attachment":[  
            {  
               "href":"http:\/\/products.example.localhost\/wp-json\/wp\/v2\/media?parent=5"
            }
         ],
         "curies":[  
            {  
               "name":"wp",
               "href":"https:\/\/api.w.org\/{rel}",
               "templated":true
            }
         ]
      }
   }
]
1
0

To access posts via meta key you need to hook into the [rest_query_vary filter].1 The example I was thinking of when I read your question is the same one found on the post @WebElaine commented. I've merely added it below:

function my_allow_meta_query( $valid_vars ) {

    $valid_vars = array_merge( $valid_vars, array( 'meta_key', 'meta_value' ) );
    return $valid_vars;
}
add_filter( 'rest_query_vars', 'my_allow_meta_query' );

Calling like so: wp-json/wp/v2/posts?filter[meta_key]=MY-KEY&filter[meta_value]=MY-VALUE


The filter is applied as part of WP_REST_Posts_Controller::prepare_items_query, shown in context here in case that helps:

protected function prepare_items_query( $prepared_args = array(), $request = null ) {
    $query_args = array();

    foreach ( $prepared_args as $key => $value ) {
        /**
         * Filters the query_vars used in get_items() for the constructed query.
         *
         * The dynamic portion of the hook name, `$key`, refers to the query_var key.
         *
         * @since 4.7.0
         *
         * @param string $value The query_var value.
         */
        $query_args[ $key ] = apply_filters( "rest_query_var-{$key}", $value );
    }

    if ( 'post' !== $this->post_type || ! isset( $query_args['ignore_sticky_posts'] ) ) {
        $query_args['ignore_sticky_posts'] = true;
    }

    // Map to proper WP_Query orderby param.
    if ( isset( $query_args['orderby'] ) && isset( $request['orderby'] ) ) {
        $orderby_mappings = array(
            'id'      => 'ID',
            'include' => 'post__in',
            'slug'    => 'post_name',
        );

        if ( isset( $orderby_mappings[ $request['orderby'] ] ) ) {
            $query_args['orderby'] = $orderby_mappings[ $request['orderby'] ];
        }
    }

    return $query_args;
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.