Lọc nhiều trường tùy chỉnh với WP REST API 2


14

Tôi muốn lọc các bài đăng dựa trên nhiều trường tùy chỉnh acf có quan hệ AND. Một cái gì đó như thế này:

$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',
            ),
        ),
    );

Tôi thậm chí có thể có nhiều bộ lọc hơn. Làm cách nào tôi có thể chuyển đổi chúng sang bộ lọc REST API 2?


Hãy xem bài đăng này và cố gắng tạo chức năng của bạn wordpress.stackexchange.com/questions/169408/
mẹo

Câu trả lời:


3

Giải pháp này làm việc với get_items()trong /lib/endpoints/class-wp-rest-posts-controller.phpcủa v2 WP Rest API.


Đầu tiên, bạn sẽ muốn xây dựng các GETđối số như bạn muốn cho a new WP_Query(). Cách dễ nhất để làm điều này là với 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 );

Nó sẽ tạo ra một cái gì đó như:

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

Mà, nếu bạn muốn đọc, bạn cũng có thể sử dụng các công cụ Chrome và decodeURIComponent('your-query-here')để dễ đọc hơn khi bạn ném nó vào URL API còn lại của JSON :

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]==

Lưu ý: Để sử dụng loại bài đăng tùy chỉnh của bạn, bạn sẽ đặt producttrước?

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


Vì vậy, bạn có truy vấn của mình nhưng chúng tôi cần hướng dẫn WP cách xử lý một số điều:

  1. Thêm hỗ trợ REST cho loại bài tùy chỉnh product
  2. Cho phép truy vấn args meta_query
  3. Phân tích cú pháp 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

Đây là một thử nghiệm tôi đã thực hiện trên Localhost:

Vì lý do bảo mật, truy vấn meta không được phép trên WP Api, trước tiên, điều bạn phải làm là thêm meta_query để cho phép rest_query bằng cách thêm chức năng này vào chủ đề wordpress của bạn 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' );

sau đó, bạn sẽ cần xây dựng truy vấn html bằng cách sử dụng chức năng này trên trang web khác sẽ lấy dữ liệu từ trang web 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);

Tôi thay đổi mảng các trường để bây giờ trông giống như các đối số truy vấn của bạn. Chuỗi truy vấn được mã hóa sẽ trông như thế này:

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

Bằng cách sử dụng urldecode(), trong trường hợp này sẽ là: urldecode('http://yourwordpreswebssite.com/wp-json/wp/v2/posts?' . $field_string);bạn sẽ có một URL như thế này:

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

Nếu bạn có thể cung cấp cho chúng tôi URL trang web trực tiếp của bạn để chúng tôi có thể kiểm tra nó bằng cách sử dụng postman trực tiếp trên trang web của bạn, bởi vì để kiểm tra nó trên localhost hoặc bất kỳ trang web WordPress hiện tại nào cũng sẽ cần để tạo loại bài đăng tùy chỉnh sản phẩm và thêm các trường meta, v.v.


Cảm ơn câu trả lời của bạn nhưng tôi đã kiểm tra với truy vấn như trong câu hỏi trên Postman và nó không hoạt động.
MinhTri

@Dan tôi đã thực hiện một số cải tiến về giải pháp, các giá trị bộ lọc giống như các đối số truy vấn của bạn, bao gồm loại bài đăng tùy chỉnh không được chỉ định trong giải pháp trước đó.
emilushi

Chúng tôi không có productphân loại. Nó hoạt động rất tốt! Đừng nghĩ về việc gói meta_querybên trong filter:)
MinhTri

@Dan Tôi rất vui khi nghe nó. Tôi đã viết một bài về nó ngày hôm qua, bạn có thể xem xét chia sẻ nó :) API WordPress REST với các trường meta .
emilushi

1
Một vài điều, trên một số máy chủ AWS, sử dụng [] làm một mảng sẽ giết yêu cầu. Bạn chỉ nên sử dụng mảng () để an toàn và cho những người có thể sao chép / dán. Ngoài ra, điều này có hỗ trợ sản phẩm CPT hay chỉ phân loại? Và cuối cùng, bạn có cần vệ sinh meta_query không? Thấy nó đã được kéo, bạn có gặp rủi ro bảo mật bằng cách chấp nhận bất cứ thứ gì người dùng cung cấp không?
jgraup

1

Bạn có thể làm điều đó mà không cần API nghỉ ngơi như thế này (Đây là bộ lọc bài đăng của tôi)

    $ paged = (get_query_var ('phân trang'))? get_query_var ('phân trang'): 1;
$ args = mảng (
        'phân trang' => $ phân trang,
        'orderby' => 'date', // сор
        'đặt hàng' => 'DESC',
    );

    // о
    if (isset ($ _GET ['price_min']) || isset ($ _GET ['price_max']) || isset ($ _GET ['type']))
        $ args ['meta_query'] = mảng ('quan hệ' => 'VÀ'); // VÀ зна ина meta meta meta meta meta meta meta meta meta meta meta meta meta meta meta meta meta meta meta meta meta meta meta meta meta meta meta meta meta meta meta meta meta meta meta meta


    if ($ loại) {
        $ args ['meta_query'] [] = mảng (
            'khóa' => 'loại',
            'giá trị' => $ loại,
        );
    };

    if ($ plan) {
        $ args ['meta_query'] [] = mảng (
            'khóa' => 'kế hoạch',
            'giá trị' => $ gói,
        );
    };

    if ($ room_num) {
        $ args ['meta_query'] [] = mảng (
            'khóa' => 'room_num',
            'giá trị' => $ room_num,
        );
    };

    if ($ etage) {
        $ args ['meta_query'] [] = mảng (
            'khóa' => 'etage',
            'giá trị' => $ etage,
        );
    };  

    if ($ price_min | | $ price_max) {
        $ args ['meta_query'] [] = mảng (
            'khóa' => 'giá',
            'value' => mảng ($ price_min, $ price_max),
            'loại' => 'số',
            'so sánh' => 'GIỮA'
        );
    };  

    if ($ area_min | | $ area_max) {
        $ args ['meta_query'] [] = mảng (
            'khóa' => 'khu vực',
            'value' => mảng ($ area_min, $ area_max),
            'loại' => 'số',
            'so sánh' => 'GIỮA'
        );
    };

1
Cảm ơn câu trả lời của bạn nhưng tôi thực sự tò mò về việc thực hiện nó với REST API v2.
MinhTri

Chà, tôi nghĩ, biến thể của tôi là tốt, nhưng nếu bạn muốn ... Thực tế là phương pháp của tôi không giới hạn ở các tham số!
Igor Fedorov

1

Trong Wordpress 4.7, filterđối số đã bị xóa.

Bạn có thể kích hoạt lại nó khi cài đặt plugin này do nhóm Wordpress cung cấp. Chỉ sau đó, bạn có thể sử dụng một trong những giải pháp được đề xuất trong các câu trả lời khác.

Tôi chưa tìm thấy giải pháp nào để thực hiện tương tự mà chưa cài đặt plugin.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.