web-dev-qa-db-fra.com

Filtrer plusieurs champs personnalisés avec WP REST API 2

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 REST filtres API 2?

14
Sohrab Taee

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


Premièrement, vous voudrez construire les arguments GET comme vous le feriez pour un new WP_Query() . Le moyen le plus simple de procéder est avec 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

Qui, si vous voulez être lisible, vous pouvez également utiliser les outils Chrome et decodeURIComponent('your-query-here') pour en faciliter la lecture lorsque vous l'aurez jeté 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 devez placer product avant ?.

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


Donc, vous avez votre requête, mais nous devons indiquer à WP comment gérer certaines choses:

  1. Ajout de REST prise en charge du type de publication personnalisé product
  2. Autoriser la requête args meta_query
  3. Analyse 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 );
3
jgraup

Voici un test que j'ai fait 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 à allowed 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 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 de 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 semblable à 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 en direct 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 sur tout site WordPress existant pour créer un type de message personnalisé et ajouter des champs méta, etc. À la vôtre!

2
emilushi

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

Vous pouvez le réactiver en installant this plugin fourni par l'équipe Wordpress. Ensuite, 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.

1
Michele Fortunato

Vous pouvez le faire sans Rest API Comme ça (c'est mon filtre de posts)

 $ paged = (get_query_var ('paged'))? get_query_var ('paged'): 1; 
 $ args = array (
 'paged' => $ paged, 
 'orderby' => 'date', // сортировка по Vous avez besoin d'aide pour votre recherche (".". "."; ";"; массив $ args ['meta_query'] если указана хендать бы одна цена или отмечен чекбокс 
 if $ _GET ['type'])) 
 $ Args ['meta_query'] = array ('relation' => 'AND'); // AND значит все условия meta_query должны выполняться 
 
 
 If ($ type) {
 $ Args ['meta_query'] []. .] 'clé' => 'type', 
 'valeur' ​​=> $ type, 
); 
}; 
 
 if ( $ plan) {
 $ args ['meta_query'] [] = array (
 'key' => 'plan', 
 'value' => $ plan, 
); 
}; 
 
 if ($ room_num) {
 $ args ['meta_query'] [] = array (
 'key' => 'room_num', 
 'valeur' ​​=> $ room_num, 
); 
}; 
 
 if ($ etage ) {
 $ args ['meta_query'] [] = array (
 'key' => 'etage', 
 'value' => $ etage, 
); 
}; 
 
 if ($ price_min || $ price_max) {
 $ args ['meta_query'] [] = array (
 'key' => 'price' , 
 'value' => tableau ($ price_min, $ price_max), 
 'type' => 'numérique', 
 'compare' => 'ENTRE ENTRE' 
); 
}; 
 
 if ($ area_min || $ area_max) {
 $ args ['meta_query'] [] = array (
 'key' => 'area' , 
 'value' => array ($ area_min, $ area_max), 
 'type' => 'numérique', 
 'compare' => 'ENTRE ENTRE' 
); 
}; 
1
Igor Fedorov