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?
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 :
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:
product
meta_query
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 );
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!
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.
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' ); };