WP REST API 2를 사용하여 여러 사용자 정의 필드 필터링


14

AND 관계가있는 여러 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 필터로 어떻게 변환 할 수 있습니까?


답변:


3

이 솔루션은 작동 get_items()/lib/endpoints/class-wp-rest-posts-controller.php 합니다 v2 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에 몇 가지 사항을 처리하는 방법을 알려야합니다.

  1. 맞춤 게시물 유형에 대한 REST 지원 추가 product
  2. 쿼리 인수 허용 meta_query
  3. 파싱 meta_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 );

2

다음은 Localhost에서 수행 한 테스트입니다.

보안상의 이유로 WP Api에서 메타 쿼리를 사용할 수 없습니다. 먼저해야 할 일은 wordpress 테마에이 함수를 추가하여 rest_query에 meta_query를 추가하는 것입니다. 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 쿼리를 작성해야합니다. 워드 프레스 웹 사이트에서 데이터를 가져옵니다.

$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을 사용하여 그것을 테스트 할 수 있습니다.


귀하의 답변에 감사하지만 Postman의 질문과 같이 쿼리로 테스트했지만 작동하지 않았습니다.
MinhTri

@Dan 나는 솔루션을 약간 개선했다. 필터 값은 이전 솔루션에서 지정되지 않은 사용자 정의 게시물 유형을 포함하여 쿼리 인수와 동일합니다.
emilushi

product분류 체계 가 없습니다 . 잘 작동합니다! meta_query안에 포장에 대해 생각하지 않았다 filter:)
MinhTri

@ Dan 나는 그것을 듣고 기쁘다. 나는 어제 그것에 대해 글을 썼다. 당신은 그것을 공유하는 것을 고려할 것이다 :) 메타 필드와 WordPress REST API .
emilushi

1
일부 AWS 서버에서 []를 배열로 사용하면 요청이 종료됩니다. 안전하고 복사 / 붙여 넣기 방법을 위해 array ()를 사용해야합니다. 또한 CPT 제품 또는 분류 체계 만 지원합니까? 마지막으로 meta_query를 삭제해야합니까? 당겨진 것을보고 사용자가 제공 한 것을 수락하여 보안 위험을 감수합니까?
jgraup

1

Rest API 없이이 작업을 수행 할 수 있습니다. 이것은 내 게시물 필터입니다.

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

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


    if ($ type) {
        $ args [ 'meta_query'] [] = 배열 ​​(
            'key'=> 'type',
            'value'=> $ type,
        );
    };

    if ($ plan) {
        $ args [ 'meta_query'] [] = 배열 ​​(
            'key'=> 'plan',
            'value'=> $ plan,
        );
    };

    if ($ room_num) {
        $ args [ 'meta_query'] [] = 배열 ​​(
            'key'=> 'room_num',
            'value'=> $ room_num,
        );
    };

    if ($ etage) {
        $ args [ 'meta_query'] [] = 배열 ​​(
            'key'=> 'etage',
            'value'=> $ etage,
        );
    };  

    if ($ price_min || $ price_max) {
        $ args [ 'meta_query'] [] = 배열 ​​(
            'key'=> '가격',
            'value'=> 배열 ($ price_min, $ price_max),
            'type'=> '숫자',
            'compare'=> '사이에'
        );
    };  

    if ($ area_min || $ area_max) {
        $ args [ 'meta_query'] [] = 배열 ​​(
            'key'=> 'area',
            'value'=> 배열 ($ area_min, $ area_max),
            'type'=> '숫자',
            'compare'=> '사이에'
        );
    };

1
귀하의 답변에 감사하지만 REST API v2를 사용하여 궁금한 점이 있습니다.
MinhTri

글쎄, 내 변형은 좋지만 원한다면 ... 내 방법이 매개 변수에 국한되지 않는다는 사실!
Igor Fedorov

1

Wordpress 4.7에서는 filter인수가 제거되었습니다.

Wordpress 팀에서 제공 한이 플러그인을 설치하여 다시 활성화 할 수 있습니다 . 그 후에 만 ​​다른 답변에서 제안 된 솔루션 중 하나를 사용할 수 있습니다.

플러그인을 설치하지 않고 동일한 작업을 수행하는 솔루션을 찾지 못했습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.