การกรองหลายฟิลด์ที่กำหนดเองด้วย WP REST API 2


14

ฉันต้องการกรองโพสต์ตามฟิลด์ที่กำหนดเองหลาย 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 ได้อย่างไร


ลองดูที่โพสต์นี้และพยายามสร้างฟังก์ชั่นของคุณwordpress.stackexchange.com/questions/169408/ …
emilushi

คำตอบ:


3

วิธีการแก้ปัญหานี้ทำงานร่วมกับ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')ทำให้อ่านง่ายขึ้นเมื่อคุณใส่ลงในURL JSON Rest APIของคุณ:

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 สิ่งแรกที่คุณต้องทำคือการเพิ่ม meta_query ไปยัง rest_query ที่ได้รับอนุญาตโดยการเพิ่มฟังก์ชั่นนี้ในธีม WordPress ของคุณ 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 เว็บไซต์สดของคุณกับเราเพื่อให้เราสามารถทดสอบได้โดยใช้บุรุษไปรษณีย์โดยตรงบนเว็บไซต์ของคุณเพราะเพื่อทดสอบบน localhost หรือเว็บไซต์ WordPress ใด ๆ ที่มีอยู่จะต้องใช้ในการสร้างประเภทโพสต์ที่กำหนดเองของผลิตภัณฑ์


ขอบคุณสำหรับคำตอบของคุณ แต่ฉันได้ทดสอบกับแบบสอบถามเช่นเดียวกับคำถามในบุรุษไปรษณีย์และมันไม่ทำงาน
MinhTri

@Dan ฉันทำการปรับปรุงบางอย่างเกี่ยวกับการแก้ปัญหาค่าตัวกรองเป็นเช่นเดียวกับข้อโต้แย้งแบบสอบถามของคุณรวมถึงประเภทโพสต์ที่กำหนดเองซึ่งไม่ได้ระบุไว้ในโซลูชันก่อนหน้า
emilushi

เราไม่มีproductอนุกรมวิธาน มันใช้งานได้ดี! ไม่ได้คิดเกี่ยวกับการวางรูปภาพmeta_queryภายในfilter:)
MinhTri

@ แดนฉันดีใจที่ได้ยิน ผมได้เขียนโพสต์เกี่ยวกับเรื่องนี้เมื่อวานนี้คุณอาจพิจารณาร่วมกัน :) WordPress REST API กับช่องเมตา
emilushi

1
สองสามสิ่งบนเซิร์ฟเวอร์ AWS บางเครื่องการใช้ [] เป็นอาร์เรย์จะฆ่าคำขอ คุณควรใช้ array () เพื่อความปลอดภัยและวิธีคัดลอก / วาง นอกจากนี้ยังสนับสนุนผลิตภัณฑ์ CPT หรือเฉพาะอนุกรมวิธาน? และสุดท้ายคุณต้องฆ่า meta_query ให้สะอาดหรือไม่? เมื่อเห็นว่ามันถูกดึงออกมาคุณมีความเสี่ยงด้านความปลอดภัยโดยยอมรับสิ่งที่ผู้ใช้จัดหาหรือไม่?
jgraup

1

คุณสามารถทำได้โดยไม่พัก 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'] = อาร์เรย์ ('ความสัมพันธ์' => 'AND'); // AND значитвсеусловия meta_query должнывыполняться


    ถ้า ($ type) {
        $ args ['meta_query'] [] = อาร์เรย์ (
            'key' => 'type',
            'value' => $ type
        );
    };

    ถ้า ($ แผน) {
        $ args ['meta_query'] [] = อาร์เรย์ (
            'key' => 'plan'
            'value' => $ แผน
        );
    };

    if ($ room_num) {
        $ args ['meta_query'] [] = อาร์เรย์ (
            'key' => 'room_num'
            'value' => $ room_num
        );
    };

    ถ้า ($ etage) {
        $ args ['meta_query'] [] = อาร์เรย์ (
            'key' => 'etage'
            'value' => $ etage
        );
    };  

    ถ้า ($ price_min || $ price_max) {
        $ args ['meta_query'] [] = อาร์เรย์ (
            'key' => 'price'
            'value' => array ($ price_min, $ price_max)
            'type' => 'ตัวเลข'
            'เปรียบเทียบ' => 'ระหว่าง'
        );
    };  

    ถ้า ($ area_min || $ area_max) {
        $ args ['meta_query'] [] = อาร์เรย์ (
            'key' => 'area',
            'value' => array ($ area_min, $ area_max),
            'type' => 'ตัวเลข'
            'เปรียบเทียบ' => 'ระหว่าง'
        );
    };

1
ขอบคุณสำหรับคำตอบของคุณ แต่ฉันอยากรู้เกี่ยวกับ REST API v2
MinhTri

ฉันคิดว่าตัวแปรของฉันดี แต่ถ้าคุณต้องการ ... ความจริงที่ว่าวิธีการของฉันไม่ได้ จำกัด เฉพาะพารามิเตอร์!
Igor Fedorov

1

ใน Wordpress 4.7 filterอาร์กิวเมนต์ได้ถูกลบออก

คุณสามารถเปิดใช้งานอีกครั้งโดยติดตั้งปลั๊กอินนี้จัดทำโดยทีมงาน Wordpress หลังจากนั้นคุณสามารถใช้หนึ่งในวิธีแก้ไขปัญหาที่เสนอในคำตอบอื่น ๆ

ฉันยังไม่พบวิธีแก้ไขปัญหาดังกล่าวโดยไม่ติดตั้งปลั๊กอินเลย

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.