17

I am trying to filter by a meta query but no matter what I try I can not make it work.

Basically I want this query in through the rest API:

wp-json/wp/v2/books?meta_query[relation]=OR&meta_query[0][key]=arkivera&meta_query[0][value]=1&meta_query[0][compare]==

Ive tried several different custom fields but it will always return all post objects.

In my functions file I've added:

function api_allow_meta_query( $valid_vars ) {

  $valid_vars = array_merge( $valid_vars, array( 'meta_query') );
  return $valid_vars;
}
add_filter( 'rest_query_vars', 'api_allow_meta_query' );

I tried finishing some documentation regarding this but couldn't, also most of the similar questions are not for wordpress 4.7 since filter[xxx] is removed.

1

3 Answers 3

11

You can write your own REST handler for custom queries if you want. In your case, the query can done by doing so:

// Register a REST route
add_action( 'rest_api_init', function () {
    //Path to meta query route
    register_rest_route( 'tchernitchenko/v2', '/my_meta_query/', array(
            'methods' => 'GET', 
            'callback' => 'custom_meta_query' 
    ) );
});

// Do the actual query and return the data
function custom_meta_query(){
    if(isset($_GET['meta_query'])) {
        $query = $_GET['meta_query'];
        // Set the arguments based on our get parameters
        $args = array (
            'relation' => $query[0]['relation'],
            array(
                'key' => $query[0]['key'],
                'value' => $query[0]['value'],
                'compare' => '=',
            ),
        );
        // Run a custom query
        $meta_query = new WP_Query($args);
        if($meta_query->have_posts()) {
            //Define and empty array
            $data = array();
            // Store each post's title in the array
            while($meta_query->have_posts()) {
                $meta_query->the_post();
                $data[] =  get_the_title();
            }
            // Return the data
            return $data;
        } else {
            // If there is no post
            return 'No post to show';
        }
    }
}

Now, all you have to do is to access:

wp-json/tchernitchenko/v2/my_meta_query?meta_query[relation]=OR&meta_query[0][key]=arkivera&meta_query[0][value]=1&meta_query[0][compare]==
1
  • Is there a way to extend this to WooCommerce Legacy API?
    – Amjad
    Commented Jan 15, 2021 at 23:49
20

Use filter rest_{CUSTOM_POST_TYPE}_query to add the post meta support in WP Rest API for any post type.

Check the Gist search post by post meta with rest API.

How to use?

http://example.org/wp-json/wp/v2/post?meta_key=<my_meta_key>&meta_value=<my_meta_value>

Example

Get posts which post meta already-visited value is true.

http://example.org/wp-json/wp/v2/post?meta_key=already-visited&meta_value=true

It ONLY lists the posts which post meta key already-visited have value true.

For reference Search post by post meta with rest api.

Available Filters

  • rest_post_query
  • rest_page_query
  • rest_attachment_query
2
  • 2
    Thank you for this! This should more likely be the accepted answer I believe.
    – jagershark
    Commented Oct 1, 2018 at 18:04
  • what about strings if we want a field with value (not null) i can retrieve latitude fields that greater that a value filter[meta_key]=latitude&filter[meta_compare]=%3C&filter[meta_value]=34.7 but i need another string field so i want to have which has value Commented Feb 20, 2019 at 14:28
5

The following code should add multiple meta queries capability to all your post types. It supports CPT (Custom Post Type) and ACF (Advanced Custom Field). Source code also available on Github.

Add it to your function.php

add_action( 'rest_api_init', 'wp_rest_filter_add_filters' );
 /**
  * Add the necessary filter to each post type
  **/
function wp_rest_filter_add_filters() {
    foreach ( get_post_types( array( 'show_in_rest' => true ), 'objects' ) as $post_type ) {
        add_filter( 'rest_' . $post_type->name . '_query', 'wp_rest_filter_add_filter_param', 10, 2 );
    }
}
/**
 * Add the filter parameter
 *
 * @param  array           $args    The query arguments.
 * @param  WP_REST_Request $request Full details about the request.
 * @return array $args.
 **/
function wp_rest_filter_add_filter_param( $args, $request ) {
    // Bail out if no filter parameter is set.
    if ( empty( $request['filter'] ) || ! is_array( $request['filter'] ) ) {
        return $args;
    }
    $filter = $request['filter'];
    if ( isset( $filter['posts_per_page'] ) && ( (int) $filter['posts_per_page'] >= 1 && (int) $filter['posts_per_page'] <= 100 ) ) {
        $args['posts_per_page'] = $filter['posts_per_page'];
    }
    global $wp;
    $vars = apply_filters( 'rest_query_vars', $wp->public_query_vars );
    function allow_meta_query( $valid_vars )
    {
        $valid_vars = array_merge( $valid_vars, array( 'meta_query', 'meta_key', 'meta_value', 'meta_compare' ) );
        return $valid_vars;
    }
    $vars = allow_meta_query( $vars );

    foreach ( $vars as $var ) {
        if ( isset( $filter[ $var ] ) ) {
            $args[ $var ] = $filter[ $var ];
        }
    }
    return $args;
}

IMHO, a more better way would to include the additional function as a seperate plugin. So even when user changed theme, your api calls won't be affected.

Therefore I've developed a plugin for meta query in WordPress. Better yet, it supports ACF too!

WP REST Filter

After installation, just do a GET request in the following format.

https://domain.com/wp-json/acf/v3/customposttype?filter[meta_key]=acfkey&filter[meta_value]=acfvalue

Check out the plugin source code from Github.

9
  • Nice plugin, however date sorting doesnt work for acf date fields!
    – Advena
    Commented Apr 30, 2018 at 10:43
  • 1
    Hi Tanckom. Thank you for your message. Can you please elaborate your issue? What have you tried? Please submit your issue to wordpress.org/support/plugin/wp-rest-filter. Our support team will get back to your there. Thank you.
    – Jack Song
    Commented Apr 30, 2018 at 17:43
  • Hey Jack, I figured out that the correct url to grab the date from acf field and sort it by asc or desc is following: domain.com/wp-json/wp/v2/…
    – Advena
    Commented Apr 30, 2018 at 20:49
  • 1
    Awesome! Glad our plugin helped! :D
    – Jack Song
    Commented May 1, 2018 at 3:53
  • It really did, keep up the good work! :)
    – Advena
    Commented May 1, 2018 at 10:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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