Filtro di più campi personalizzati con l'API REST WP 2


14

Voglio filtrare i post in base a più campi personalizzati acf con relazione AND. Qualcosa come questo:

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

Potrei anche avere più filtri. Come posso convertirli in filtri REST API 2?


Dai un'occhiata a questo post e prova a creare la tua funzione wordpress.stackexchange.com/questions/169408/…
emilushi,

Risposte:


3

Questa soluzione funziona con get_items()in /lib/endpoints/class-wp-rest-posts-controller.phpdel v2 WP Rest API.


Innanzitutto, vorrai costruire gli GETargomenti come faresti per a new WP_Query(). Il modo più semplice per farlo è con 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 );

Produrrà qualcosa come:

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

Che, se vuoi leggere, puoi anche usare gli strumenti di Chrome e decodeURIComponent('your-query-here')renderlo più facile da leggere quando lo butti nell'URL dell'API di riposo 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]==

Nota: per utilizzare il tipo di post personalizzato che hai inserito in productprecedenza?

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


Quindi hai la tua domanda ma dobbiamo istruire WP su come gestire alcune cose:

  1. Aggiunta del supporto REST per il tipo di post personalizzato product
  2. Consentire la query args meta_query
  3. parsing 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

Ecco un test che ho fatto su Localhost:

Per motivi di sicurezza, la meta query non è consentita su WP Api, innanzitutto è necessario aggiungere meta_query a rest_query consentita aggiungendo questa funzione sul tema 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' );

dopodiché dovrai creare la query html usando questa funzione sull'altro sito Web che otterrà i dati dal sito 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);

Cambio l'array dei campi in modo che ora assomiglino ai tuoi argomenti di query. La stringa di query codificata sarà simile alla seguente:

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

Usando urldecode(), che in questo caso sarà: urldecode('http://yourwordpreswebssite.com/wp-json/wp/v2/posts?' . $field_string);avrai un URL come questo:

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

Se puoi fornirci l'URL del tuo sito web dal vivo in modo da poterlo testare usando il postino direttamente sul tuo sito web, perché per testarlo su localhost o qualsiasi sito WordPress esistente sarà necessario creare il tipo di post personalizzato del prodotto e aggiungere meta campi ecc. Saluti!


Grazie per la tua risposta, ma ho testato la query come nella domanda su Postman e non ha funzionato.
MinhTri,

@Dan ho apportato alcuni miglioramenti alla soluzione, i valori del filtro sono gli stessi degli argomenti della query, incluso il tipo di post personalizzato che non è stato specificato nella soluzione precedente.
emilushi,

Non abbiamo producttassonomia. Funziona benissimo! Non pensavo di avvolgermi meta_querydentro filter:)
MinhTri

@Dan Sono felice di sentirlo. Ho scritto un post a riguardo ieri, potresti prendere in considerazione la condivisione :) API REST WordPress con meta campi .
emilushi,

1
Un paio di cose, su alcuni server AWS, l'uso di [] come un array ucciderà la richiesta. Dovresti semplicemente usare array () per sicurezza e per quelli come potrebbe copiare / incollare. Inoltre, questo supporta il prodotto CPT o solo la tassonomia? E infine, devi disinfettare meta_query? Visto che è stato tirato, corri un rischio per la sicurezza accettando qualcosa che un utente fornisce?
jgraup,

1

Puoi farlo senza API Rest in questo modo (È il mio filtro post)

    $ 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 ('relazione' => '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' => 'TRA'
        );
    };  

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

1
Grazie per la risposta, ma sono davvero curioso di farlo con l'API REST v2.
MinhTri,

Beh, penso, la mia variante è buona, ma se vuoi ... Il fatto che il mio metodo non si limiti ai parametri!
Igor Fedorov,

1

In Wordpress 4.7 l' filterargomento è stato rimosso.

Puoi riattivarlo installando questo plugin fornito dal team di Wordpress. Solo dopo puoi utilizzare una delle soluzioni proposte nelle altre risposte.

Non ho ancora trovato una soluzione per fare lo stesso senza installare il plugin.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.