使用WP REST API 2过滤多个自定义字段

时间:2016-05-14 作者:Sohrab Taee

我想根据多个acf自定义字段和关系筛选帖子。类似这样:

$args = array(
        \'post_type\'  => \'product\',
        \'meta_query\' => array(
            \'relation\' => \'AND\',
            array(
                \'key\'     => \'color\',
                \'value\'   => \'blue\',
                \'compare\' => \'=\',
            ),
            array(
                \'key\'     => \'price\',
                \'value\'   => array( 20, 100 ),
                \'type\'    => \'numeric\',
                \'compare\' => \'BETWEEN\',
            ),
        ),
    );
我甚至可能有更多的过滤器。如何将这些转换为REST API 2过滤器?

5 个回复
SO网友:jgraup

此解决方案适用于get_items() 在里面/lib/endpoints/class-wp-rest-posts-controller.phpv2 WP Rest API.

首先,您需要构建GET 像你这样的争论new WP_Query(). 最简单的方法是http_build_query().

$args = array (
    \'filter\' => array (
        \'meta_query\' => array (
            \'relation\' => \'AND\',
            array (
                \'key\'     => \'color\',
                \'value\'   => \'blue\',
                \'compare\' => \'=\',
            ),
            array (
                \'key\'     => \'test\',
                \'value\'   => \'testing\',
                \'compare\' => \'=\',
            ),
        ),
    ),
);
$field_string = http_build_query( $args );
它将产生如下结果:

filter%5Bmeta_query%5D%5Brelation%5D=AND&filter%5Bmeta_query%5D%5B0%5D%5Bkey%5D=color&filter%5Bmeta_query%5D%5B0%5D%5Bvalue%5D=blue&filter%5Bmeta_query%5D%5B0%5D%5Bcompare%5D=%3D&filter%5Bmeta_query%5D%5B1%5D%5Bkey%5D=test&filter%5Bmeta_query%5D%5B1%5D%5Bvalue%5D=testing&filter%5Bmeta_query%5D%5B1%5D%5Bcompare%5D=%3D

如果您希望可读,还可以使用Chrome工具和decodeURIComponent(\'your-query-here\') 当你把它扔进你的JSON Rest API URL:

https://demo.wp-api.org/wp-json/wp/v2/product?filter[meta_query][relation]=AND&filter[meta_query][0][key]=color&filter[meta_query][0][value]=blue&filter[meta_query][0][compare]==&filter[meta_query][1][key]=test&filter[meta_query][1][value]=testing&filter[meta_query][1][compare]==

注意:要使用自定义的帖子类型,您可以将product 之前?

/wp-json/wp/v2/<custom-post-type>?filter[meta_query]


所以你有你的疑问,但我们需要指导WP如何处理一些事情:

为自定义帖子类型添加REST支持product允许查询参数meta_querymeta_query


// 1) Add CPT Support <product>


function wpse_20160526_add_product_rest_support() {
    global $wp_post_types;

    //be sure to set this to the name of your post type!
    $post_type_name = \'product\';
    if( isset( $wp_post_types[ $post_type_name ] ) ) {
        $wp_post_types[$post_type_name]->show_in_rest = true;
        $wp_post_types[$post_type_name]->rest_base = $post_type_name;
        $wp_post_types[$post_type_name]->rest_controller_class = \'WP_REST_Posts_Controller\';
    }
}

add_action( \'init\', \'wpse_20160526_add_product_rest_support\', 25 );


// 2) Add `meta_query` support in the GET request

function wpse_20160526_rest_query_vars( $valid_vars ) {
    $valid_vars = array_merge( $valid_vars, array(  \'meta_query\'  ) ); // Omit meta_key, meta_value if you don\'t need them
    return $valid_vars;
}

add_filter( \'rest_query_vars\', \'wpse_20160526_rest_query_vars\', PHP_INT_MAX, 1 );


// 3) Parse Custom Args

function wpse_20160526_rest_product_query( $args, $request ) {

    if ( isset( $args[ \'meta_query\' ] ) ) {

        $relation = \'AND\';
        if( isset($args[\'meta_query\'][\'relation\']) && in_array($args[\'meta_query\'][\'relation\'], array(\'AND\', \'OR\'))) {
            $relation = sanitize_text_field( $args[\'meta_query\'][\'relation\'] );
        }
        $meta_query = array(
            \'relation\' => $relation
        );

        foreach ( $args[\'meta_query\'] as $inx => $query_req ) {
        /*
            Array (

                [key] => test
                [value] => testing
                [compare] => =
            )
        */
            $query = array();

            if( is_numeric($inx)) {

                if( isset($query_req[\'key\'])) {
                    $query[\'key\'] = sanitize_text_field($query_req[\'key\']);
                }
                if( isset($query_req[\'value\'])) {
                    $query[\'value\'] = sanitize_text_field($query_req[\'value\']);
                }
                if( isset($query_req[\'type\'])) {
                    $query[\'type\'] = sanitize_text_field($query_req[\'type\']);
                }
                if( isset($query_req[\'compare\']) && in_array($query_req[\'compare\'], array(\'=\', \'!=\', \'>\',\'>=\',\'<\',\'<=\',\'LIKE\',\'NOT LIKE\',\'IN\',\'NOT IN\',\'BETWEEN\',\'NOT BETWEEN\', \'NOT EXISTS\')) ) {
                    $query[\'compare\'] = sanitize_text_field($query_req[\'compare\']);
                }
            }

            if( ! empty($query) ) $meta_query[] = $query;
        }

        // replace with sanitized query args
        $args[\'meta_query\'] = $meta_query;
    }

    return $args;
}
add_action( \'rest_product_query\', \'wpse_20160526_rest_product_query\', 10, 2 );

SO网友:emilushi

下面是我在Localhost上进行的测试:

出于安全原因,WP-Api上不允许使用meta查询,首先要做的是通过在wordpress主题上添加此函数,将meta\\u查询添加到允许的rest\\u查询中functions.php

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\' );
之后,您需要在另一个网站上使用此功能构建html查询,该网站将从wordpress网站获取数据

$curl = curl_init();
$fields = array (
  \'filter[meta_query]\' => array (
    \'relation\' => \'AND\',
      array (
        \'key\' => \'color\',
        \'value\' => \'blue\',
        \'compare\' => \'=\'
      ),
      array (
        \'key\' => \'price\',
        \'value\' => array ( 20, 100 ),
        \'type\' => \'numeric\',
        \'compare\' => \'BETWEEN\'
      ),
    ),
  );

$field_string = http_build_query($fields);

curl_setopt_array($curl, array (
    CURLOPT_RETURNTRANSFER => 1,
    CURLOPT_URL => \'http://yourwordpreswebssite.com/wp-json/wp/v2/posts?\' . $field_string
  )
);

$result = curl_exec($curl);

echo htmlentities($result);
我更改了字段数组,使其现在看起来像您的查询参数。编码的查询字符串如下所示:

http://yourwordpreswebssite.com/wp-json/wp/v2/posts?filter%5Btaxonomy%5D=product&filter%5Bmeta_query%5D%5Brelation%5D=AND&filter%5Bmeta_query%5D%5B0%5D%5Bkey%5D=color&filter%5Bmeta_query%5D%5B0%5D%5Bvalue%5D=blue&filter%5Bmeta_query%5D%5B0%5D%5Bcompare%5D=%3D&filter%5Bmeta_query%5D%5B1%5D%5Bkey%5D=price&filter%5Bmeta_query%5D%5B1%5D%5Bvalue%5D%5B0%5D=20&filter%5Bmeta_query%5D%5B1%5D%5Bvalue%5D%5B1%5D=100&filter%5Bmeta_query%5D%5B1%5D%5Btype%5D=numeric&filter%5Bmeta_query%5D%5B1%5D%5Bcompare%5D=BETWEEN
通过使用urldecode(), 在这种情况下:urldecode(\'http://yourwordpreswebssite.com/wp-json/wp/v2/posts?\' . $field_string); 您将拥有如下URL:

http://yourwordpreswebssite.com/wp-json/wp/v2/posts?filter[taxonomy]=product&filter[meta_query][relation]=AND&filter[meta_query][0][key]=color&filter[meta_query][0][value]=blue&filter[meta_query][0][compare]==&filter[meta_query][1][key]=price&filter[meta_query][1][value][0]=20&filter[meta_query][1][value][1]=100&filter[meta_query][1][type]=numeric&filter[meta_query][1][compare]=BETWEEN
如果您可以为我们提供您的实时网站URL,那么我们可以直接在您的网站上使用postman进行测试,因为要在localhost或任何现有WordPress网站上进行测试,需要创建产品自定义帖子类型和添加元字段等。干杯!

SO网友:Igor Fedorov

您可以这样做,而无需Rest API(这是我的帖子过滤器)

    $paged = (get_query_var(\'paged\')) ? get_query_var(\'paged\') : 1;
$args = array(
        \'paged\' => $paged,
        \'orderby\' => \'date\', // сортировка по дате у нас будет в любом случае (но вы можете изменить/доработать это)
        \'order\' => \'DESC\',
    );

    // создаём массив $args[\'meta_query\'] если указана хотя бы одна цена или отмечен чекбокс
    if( isset( $_GET[\'price_min\'] ) || isset( $_GET[\'price_max\'] ) || isset( $_GET[\'type\'] ) )
        $args[\'meta_query\'] = array( \'relation\'=>\'AND\' ); // AND значит все условия meta_query должны выполняться


    if( $type ){
        $args[\'meta_query\'][] = array(
            \'key\' => \'type\',
            \'value\' => $type,
        );
    };

    if( $plan ){
        $args[\'meta_query\'][] = array(
            \'key\' => \'plan\',
            \'value\' => $plan,
        );
    };

    if( $room_num ){
        $args[\'meta_query\'][] = array(
            \'key\' => \'room_num\',
            \'value\' => $room_num,
        );
    };

    if( $etage ){
        $args[\'meta_query\'][] = array(
            \'key\' => \'etage\',
            \'value\' => $etage,
        );
    };  

    if( $price_min || $price_max ){
        $args[\'meta_query\'][] = array(
            \'key\' => \'price\',
            \'value\' => array( $price_min, $price_max ),
            \'type\' => \'numeric\',
            \'compare\' => \'BETWEEN\'
        );
    };  

    if( $area_min || $area_max ){
        $args[\'meta_query\'][] = array(
            \'key\' => \'area\',
            \'value\' => array( $area_min, $area_max ),
            \'type\' => \'numeric\',
            \'compare\' => \'BETWEEN\'
        );
    };

SO网友:Michele Fortunato

在Wordpress 4.7中filter 参数已删除。

您可以在安装时重新激活它this Wordpress团队提供的插件。只有在这之后,你才能使用其他答案中提出的一种解决方案。

我还没有找到一个不安装插件就能做到这一点的解决方案。

SO网友:Rahman Rezaee

首先添加插件或复制所有代码并粘贴所有插件函数。此链接的phphttps://github.com/WP-API/rest-filter

  • 使用此
    ?filter[meta_query][relation]=AND
    &filter[meta_query][0][key]=REAL_HOMES_property_price
    &filter[meta_query][0][value][0]=10
    &filter[meta_query][0][value][1]=10000001
    &filter[meta_query][0][compare]=\'\'
    &filter[meta_query][1][key]=REAL_HOMES_property_price
    &filter[meta_query][1][value]=10
    &filter[meta_query][1][compare]=\'=\'