Filtrage de plusieurs champs personnalisés avec WP REST API 2

13

Je souhaite filtrer les publications en fonction de plusieurs champs personnalisés acf avec une relation AND. Quelque chose comme ça:

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

Je pourrais même avoir plus de filtres. Comment puis-je les convertir en filtres REST API 2?

    
posée Sohrab Taee 14.05.2016 - 07:57

4 réponses

3

Cette solution fonctionne avec get_items() dans /lib/endpoints/class-wp-rest-posts-controller.php du v2 WP Rest API .

Tout d'abord, vous voudrez construire les arguments GET comme vous le feriez pour new WP_Query() . Le moyen le plus simple de procéder consiste à 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 );

Cela produira quelque chose comme:

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

Ce qui, si vous voulez être lisible, vous pouvez également utiliser les outils de Chrome et decodeURIComponent('your-query-here') pour faciliter la lecture lorsque vous l'incluez dans votre URL de l'API JSON Rest :

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

Remarque: pour utiliser votre type de publication personnalisé, vous devriez mettre product avant ?

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

Vous avez donc votre requête mais nous devons indiquer à WP comment gérer quelques opérations:

  1. Ajout de la prise en charge REST pour le type de publication personnalisé product
  2. Autoriser la requête args meta_query
  3. Analyse de 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 );
    
réponse donnée jgraup 26.05.2016 - 07:00
2

Voici un test que j'ai effectué sur Localhost:

Pour des raisons de sécurité, la méta-requête n'est pas autorisée sur WP Api. Tout d'abord, vous devez ajouter meta_query à autorise rest_query en ajoutant cette fonction sur votre thème 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' );

après cela, vous aurez besoin de construire la requête HTML en utilisant cette fonction sur l’autre site Web qui obtiendra les données du site 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);

Je change le tableau des champs afin que l'apparence ressemble maintenant à vos arguments de requête. La chaîne de requête codée ressemblera à ceci:

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

En utilisant urldecode() , qui dans ce cas sera: urldecode('http://yourwordpreswebssite.com/wp-json/wp/v2/posts?' . $field_string); , vous obtiendrez une URL similaire à celle-ci:

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

Si vous pouvez nous fournir l'URL de votre site Web actif afin que nous puissions le tester à l'aide de postman directement sur votre site Web, car il sera nécessaire de le tester sur localhost ou tout site WordPress existant sera nécessaire pour créer un type de publication personnalisé, ajouter des champs méta, etc. À la vôtre!

    
réponse donnée emilushi 25.05.2016 - 17:07
1

Vous pouvez le faire sans API Rest Comme ça (Ce sont mes filtres de messages)

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

    if( $area_min || $area_max ){
        $args['meta_query'][] = array(
            'key' => 'area',
            'value' => array( $area_min, $area_max ),
            'type' => 'numeric',
            'compare' => 'BETWEEN'
        );
    };
    
réponse donnée Igor Fedorov 25.05.2016 - 16:20
1

Dans Wordpress 4.7, l'argument filter a été supprimé.

Vous pouvez le réactiver en installant ce plugin fourni par l'équipe Wordpress. C’est seulement après que vous pourrez utiliser l’une des solutions proposées dans les autres réponses.

Je n'ai pas encore trouvé de solution pour faire la même chose sans installer le plugin.

    
réponse donnée Michele Fortunato 12.01.2017 - 06:51

Lire d'autres questions sur les étiquettes