it-swarm.com.de

Mehrere benutzerdefinierte Felder filtern mit WP REST API 2

Ich möchte Posts basierend auf mehreren benutzerdefinierten ACF-Feldern mit UND-Verknüpfung filtern. Etwas wie das:

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

Ich könnte sogar mehr Filter haben. Wie kann ich diese in REST API 2-Filter konvertieren?

14
Sohrab Taee

Diese Lösung funktioniert mit get_items() in /lib/endpoints/class-wp-rest-posts-controller.php des v2 WP Rest API .


Zunächst möchten Sie die Argumente GET wie für eine new WP_Query() konstruieren. Am einfachsten geht das mit 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 );

Es wird so etwas produzieren wie:

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

Wenn Sie lesbar sein möchten, können Sie auch Chrome-Tools und decodeURIComponent('your-query-here') verwenden, um das Lesen zu vereinfachen, wenn Sie es in Ihre JSON Rest API-URL werfen :

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

Hinweis: Um Ihren benutzerdefinierten Beitragstyp zu verwenden, setzen Sie product vor ?.

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


Sie haben also Ihre Frage, aber wir müssen WP anweisen, wie ein paar Dinge zu tun sind:

  1. Hinzufügen von REST Unterstützung für den benutzerdefinierten Beitragstyp product
  2. Zulassen der Abfrage 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 );
3
jgraup

Hier ist ein Test, den ich auf Localhost gemacht habe:

Aus Sicherheitsgründen ist eine Meta-Abfrage für WP API nicht zulässig. Zuerst müssen Sie meta_query zu erlaubter rest_query hinzufügen, indem Sie diese Funktion in Ihrem WordPress-Design hinzufügen. 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' );

danach müssen Sie die HTML-Abfrage mithilfe dieser Funktion auf der anderen Website erstellen, die die Daten von der WordPress-Website abruft

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

Ich ändere das Feldarray so, dass es jetzt wie Ihre Abfrageargumente aussieht. Die codierte Abfragezeichenfolge sieht folgendermaßen aus:

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

Wenn Sie urldecode() verwenden, in diesem Fall urldecode('http://yourwordpreswebssite.com/wp-json/wp/v2/posts?' . $field_string);, haben Sie eine URL wie die folgende:

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

Wenn Sie uns Ihre Live-Website-URL zur Verfügung stellen können, damit wir sie mit postman direkt auf Ihrer Website testen können, da Sie zum Testen auf localhost oder einer vorhandenen WordPress-Site einen benutzerdefinierten Produktposttyp erstellen und Metafelder usw. usw. hinzufügen müssen.

2
emilushi

In Wordpress 4.7 wurde das Argument filter entfernt.

Sie können es reaktivieren, indem Sie das vom Wordpress-Team bereitgestellte this Plugin installieren. Erst danach können Sie eine der in den anderen Antworten vorgeschlagenen Lösungen verwenden.

Ich habe noch keine Lösung gefunden, um dasselbe zu tun, ohne das Plugin zu installieren.

1

Du kannst es auch ohne Rest API machen.

 $ paged = (get_query_var ('paged'))? get_query_var ('paged'): 1; 
 $ args = array (
 'paged' => $ paged, 
 'orderby' => 'date', // сортировка по Sie können den Befehl 
 'order' => 'DESC', 
); [ массив $ args ['meta_query'] если указана хотя бы одна цена или отмечен чекбокс 
 if (isset ($ _GET ['price_min']) || $ _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' 
); 
}; 
1
Igor Fedorov