WP REST API 2 ile birden fazla özel alana filtre uygulama


14

Mesajları AND ilişkisiyle birden çok acf özel alanına göre filtrelemek istiyorum. Bunun gibi bir şey:

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

Daha fazla filtrem bile olabilir. Bunları REST API 2 filtrelerine nasıl dönüştürebilirim?


Yanıtlar:


3

Bu çözüm ile çalışır get_items()içinde /lib/endpoints/class-wp-rest-posts-controller.phpbir v2 WP Rest API.


İlk olarak, sizin GETgibi argümanları oluşturmak istersiniz new WP_Query(). Bunu yapmanın en kolay yolu 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 );

Gibi bir şey üretecek:

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

Okunabilir olmasını istiyorsanız, Chrome araçlarını da kullanabilirsiniz ve JSON Rest API URL'nizedecodeURIComponent('your-query-here') attığınızda okunmasını kolaylaştırmak için :

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

Not: Daha productönce koyacağınız özel yazı türünüzü kullanmak için?

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


Sorgunuz var, ancak WP'ye birkaç şeyi nasıl ele alacağımızı bildirmemiz gerekiyor:

  1. Özel gönderi türü için REST desteği ekleme product
  2. Sorgu değişkenlerine izin verme meta_query
  3. ayrıştırma 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

İşte Localhost üzerinde yaptığım bir test:

Güvenlik nedeniyle WP Api'de meta sorgusuna izin verilmez, önce yapmanız gereken, wordpress temanıza bu işlevi ekleyerek izin verilen rest_query'ye meta_query eklemektir. 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' );

bundan sonra wordpress web sitesinden veri alacak diğer web sitesinde bu işlevi kullanarak html sorgusu oluşturmak gerekir

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

Fields dizisini değiştiriyorum, böylece şimdi sorgu argümanlarınız gibi görünüyorum. Kodlanmış sorgu dizesi şöyle görünecektir:

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

Kullanarak urldecode(), bu durumda: aşağıdakine urldecode('http://yourwordpreswebssite.com/wp-json/wp/v2/posts?' . $field_string);benzer bir URL'niz olur:

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

Bize canlı web sitesi URL'nizi sağlayabilirseniz, böylece doğrudan web sitenizde postacı kullanarak test edebiliriz, çünkü localhost veya mevcut herhangi bir WordPress sitesinde test etmek için ürün özel posta türü oluşturmak ve meta alanları vb.


Cevabınız için teşekkürler, ancak Postacı'daki soruda olduğu gibi sorguyu test ettim ve işe yaramadı.
MinhTri

@ Çözüm üzerinde bazı iyileştirmeler yapabilir miyim, filtre değerleri, önceki çözümde belirtilmeyen özel yazı türü de dahil olmak üzere sorgu argümanlarınızla aynıdır.
emilushi

Biz yok producttaksonomisi. Harika çalışıyor! Sarma düşünmedim meta_queryfilter:)
MinhTri

@ Bunu duyduğuma sevindim. Dün bu konuda bir yazı yazdım, paylaşmayı düşünebilirsiniz :) WordPress REST API'sı meta alanlarıyla .
emilushi

1
Bazı AWS sunucularında bir dizi olarak [] kullanılması isteği iptal eder. Güvenli olmak ve kopyalamak / yapıştırmak için diziyi () kullanmanız yeterlidir. Ayrıca, bu CPT ürününü veya sadece sınıflandırmayı destekliyor mu? Son olarak, meta_query'yi sterilize etmeniz gerekiyor mu? Çekildiğini görünce, bir kullanıcının sağladığı herhangi bir şeyi kabul ederek bir güvenlik riski taşıyor musunuz?
jgraup

1

Dinlenme API'sı olmadan bunu yapabilirsiniz (Bu benim yayınlarım filtresidir)

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

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


    if ($ type) {
        $ args ['meta_query'] [] = dizi (
            'anahtar' => 'tür',
            'value' => $ türü,
        );
    };

    if ($ plan) {
        $ args ['meta_query'] [] = dizi (
            'key' => 'plan',
            'değer' => $ plan,
        );
    };

    if ($ room_num) {
        $ args ['meta_query'] [] = dizi (
            'key' => 'room_num',
            'değer' => $ oda_sayısı,
        );
    };

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

    eğer ($ price_min || $ price_max) {
        $ args ['meta_query'] [] = dizi (
            'anahtar' => 'fiyat',
            'değer' => dizi ($ price_min, $ price_max),
            'type' => 'sayısal',
            'karşılaştır' => 'ARASINDA'
        );
    };  

    eğer ($ area_min || $ area_max) {
        $ args ['meta_query'] [] = dizi (
            'key' => 'alan',
            'değer' => dizi ($ area_min, $ area_max),
            'type' => 'sayısal',
            'karşılaştır' => 'ARASINDA'
        );
    };

1
Cevabınız için teşekkürler, ancak REST API v2 ile yapmayı gerçekten çok merak ediyorum.
MinhTri

Sanırım benim varyantım iyi, ama isterseniz ... Metodumun parametrelerle sınırlı olmaması!
Igor Fedorov

1

Wordpress 4.7'de filterargüman kaldırıldı.

Wordpress ekibi tarafından sağlanan bu eklentiyi yükleyerek yeniden etkinleştirebilirsiniz . Ancak bundan sonra diğer cevaplarda önerilen çözümlerden birini kullanabilirsiniz.

Eklentiyi yüklemeden aynı şeyi yapmak için henüz bir çözüm bulamadım.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.