Filtrare più campi personalizzati con WP REST API 2

14 mag 2016, 08:57:12
Visualizzazioni: 16.3K
Voti: 18

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

$args = array(
        'post_type'  => 'product', // Tipo di post
        'meta_query' => array(
            'relation' => 'AND', // Relazione tra i filtri
            array(
                'key'     => 'color', // Campo colore
                'value'   => 'blue', // Valore blu
                'compare' => '=', // Operatore di confronto
            ),
            array(
                'key'     => 'price', // Campo prezzo
                'value'   => array( 20, 100 ), // Intervallo di valori
                'type'    => 'numeric', // Tipo numerico
                'compare' => 'BETWEEN', // Operatore between
            ),
        ),
    );

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

1
Commenti

Dai un'occhiata a questo post e prova a creare la tua funzione http://wordpress.stackexchange.com/questions/169408/wp-json-rest-api-ryan-mccue-how-to-query-posts-with-specific-meta-data-with-a

emilushi emilushi
25 mag 2016 16:03:00
Tutte le risposte alla domanda 5
0

Questa soluzione funziona con get_items() nel file /lib/endpoints/class-wp-rest-posts-controller.php dell'API REST v2 di WordPress.


Per prima cosa, dovrai costruire gli argomenti GET come faresti per una 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

Se vuoi renderlo leggibile, puoi anche usare gli strumenti di Chrome e decodeURIComponent('your-query-here') per semplificare la lettura quando lo inserisci nel tuo URL dell'API REST 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 usare il tuo custom post type, dovresti inserire product prima del ?

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


Quindi hai la tua query, ma dobbiamo istruire WordPress su come gestire alcune cose:

  1. Aggiungere il supporto REST per il custom post type product
  2. Permettere gli argomenti della query meta_query
  3. Analizzare meta_query

// 1) Aggiungi supporto CPT <product>


function wpse_20160526_add_product_rest_support() {
    global $wp_post_types;

    //assicurati di impostare questo con il nome del tuo 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) Aggiungi supporto `meta_query` nella richiesta GET

function wpse_20160526_rest_query_vars( $valid_vars ) {
    $valid_vars = array_merge( $valid_vars, array(  'meta_query'  ) ); // Ometti meta_key, meta_value se non ti servono
    return $valid_vars;
}

add_filter( 'rest_query_vars', 'wpse_20160526_rest_query_vars', PHP_INT_MAX, 1 );


// 3) Analizza Argomenti Personalizzati

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;
        }

        // sostituisci con gli argomenti della query sanificati
        $args['meta_query'] = $meta_query;
    }

    return $args;
}
add_action( 'rest_product_query', 'wpse_20160526_rest_product_query', 10, 2 );
26 mag 2016 08:00:23
8

Ecco un test che ho eseguito in Localhost:

Per motivi di sicurezza, la meta query non è consentita nell'API di WordPress. La prima cosa da fare è aggiungere meta_query alle query REST consentite inserendo questa funzione nel file functions.php del tuo tema WordPress:

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

Dopo di che, dovrai costruire la query HTML utilizzando questa funzione sull'altro sito web che recupererà i dati dal sito 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);

Ho modificato l'array fields in modo che ora corrisponda ai tuoi argomenti di query. La stringa di query codificata apparirà così:

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

Utilizzando urldecode(), che in questo caso sarà: urldecode('http://yourwordpreswebssite.com/wp-json/wp/v2/posts?' . $field_string);, otterrai 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 live, possiamo testarlo direttamente sul tuo sito utilizzando Postman, poiché per testarlo in localhost o su qualsiasi sito WordPress esistente sarà necessario creare un custom post type per i prodotti e aggiungere meta field, ecc. Saluti!

25 mag 2016 18:07:09
Commenti

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

James Vu James Vu
26 mag 2016 04:22:15

@Dan ho apportato alcuni miglioramenti alla soluzione, i valori del filtro sono gli stessi degli argomenti della tua query, incluso il custom post type che non era specificato nella soluzione precedente.

emilushi emilushi
26 mag 2016 09:54:20

Non abbiamo la tassonomia product. Funziona alla grande! Non avevo pensato di racchiudere meta_query dentro filter :)

James Vu James Vu
26 mag 2016 13:33:40

@Dan Sono contento di sentirlo. Ho scritto un post al riguardo ieri, potresti valutare di condividerlo :) WordPress REST API con campi meta.

emilushi emilushi
26 mag 2016 13:45:10

Un paio di cose, su alcuni server AWS, usare [] come array può bloccare la richiesta. Dovresti usare semplicemente array() per essere sicuro e per chi potrebbe copiare/incollare. Inoltre, questo supporta il CPT product o solo la tassonomia? E infine, è necessario sanitizzare meta_query? Visto che è stato estratto, corri un rischio di sicurezza accettando qualsiasi cosa fornisca un utente?

jgraup jgraup
26 mag 2016 15:12:41

@Eduart So come farlo funzionare per me stesso basandomi sulla tua idea ma dovresti modificare anche la risposta.

James Vu James Vu
26 mag 2016 16:19:55

@jgraup grazie mille per il tuo commento. Non sapevo questo fatto riguardo ai server AWS. I Custom post types e le Custom taxonomy dovrebbero essere registrati con l'API REST prima e sicuramente dovrebbe essere usata la validazione sugli input e l'escape sugli output. Il motivo per cui non ho usato la sanitizzazione è perché l'ho testato solo sull'output per i custom fields che avevo già validato in precedenza sugli input. Ma hai ragione, dovrebbe essere migliorato per altri utenti che si limiteranno a copiare e incollare il codice.

emilushi emilushi
26 mag 2016 21:33:19

Alcuni server AWS consentono solo PHP 5.3, che non è il massimo, ma è così. Quindi è un errore di sintassi in 5.3.

jgraup jgraup
26 mag 2016 22:04:52
Mostra i restanti 3 commenti
0
  1. prima aggiungi il plugin o copia tutto il codice e incollalo nel functions.php da questo link https://github.com/WP-API/rest-filter
  2. usa questo

?filter[meta_query][relation]=AND
&filter[meta_query][0][key]=REAL_HOMES_property_price
&filter[meta_query][0][value][0]=10
&filter[meta_query][0][value][1]=10000001
&filter[meta_query][0][compare]=''
&filter[meta_query][1][key]=REAL_HOMES_property_price
&filter[meta_query][1][value]=10
&filter[meta_query][1][compare]='='

7 apr 2020 12:51:48
2

Puoi farlo senza Rest API In questo modo (È il mio filtro per i post)

    $paged = (get_query_var('paged')) ? get_query_var('paged') : 1;
$args = array(
        'paged' => $paged,
        'orderby' => 'date', // l'ordinamento per data sarà sempre presente (ma puoi modificarlo/personalizzarlo)
        'order' => 'DESC',
    );

    // creiamo l'array $args['meta_query'] se è specificato almeno un prezzo o è selezionata una checkbox
    if( isset( $_GET['price_min'] ) || isset( $_GET['price_max'] ) || isset( $_GET['type'] ) )
        $args['meta_query'] = array( 'relation'=>'AND' ); // AND significa che tutte le condizioni meta_query devono essere soddisfatte


    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' => 'BETWEEN'
        );
    };  

    if( $area_min || $area_max ){
        $args['meta_query'][] = array(
            'key' => 'area',
            'value' => array( $area_min, $area_max ),
            'type' => 'numeric',
            'compare' => 'BETWEEN'
        );
    };
25 mag 2016 17:20:09
Commenti

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

James Vu James Vu
25 mag 2016 17:27:06

Beh, penso che la mia variante sia buona, ma se vuoi... Il fatto è che il mio metodo non è limitato ai parametri!

Igor Fedorov Igor Fedorov
25 mag 2016 17:31:35
0

In WordPress 4.7 l'argomento filter è stato rimosso.

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

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

12 gen 2017 07:51:54