WooCommerce REST API : query products by multiple attributes

喜夏-厌秋 提交于 2020-08-05 09:46:11

问题


According to the API : http://woocommerce.github.io/woocommerce-rest-api-docs/#list-all-products we can filter products by a single attribute. But Is it impossible to search by multiple attributes through API ?

Example : "I want red shirts". Here attribute is color and attribute term is red. To accomplish the search, the query string goes like this : products?category=17&attribute=pa_color&attribute_term=22&

And we get the red shirts only.

But for "I want red medium shirts" , here an additional size attribute with value medium is encountered. And according to the API there is no way to associate both the color and the size attributes in the query string. So the query -

products?category=17&attribute=pa_color&attribute_term=22&attribute=pa_size&attribute_term=24& 

returns all products from the store

Is there any workaround ?


回答1:


I have written custom query that does it all :D This is a callback function. All you need to do is create new endpoint with this callback:

Here is a documentation:

category - string (category slug) - filter by products category.
per_page - int (default - from admin) - show items on one page.
offset - int (default - 1) - show page number.
order - string (ASC/DESC, default: desc) - order products ascending or descending.
orderby - string (name, price, default: name) - order products by key.
filter - array
[pa_attribute_name (string) ]  = array of ID's.
[min_price (string) ] = int.
[max_price (string) ] = int.

Example:

/wp-json/go/v1/products/?category=smartphones&filter[pa_brand]=87,88&filter[pa_colour]=17&filter[min_price]=1&filter[max_price]=50&per_page=10&offset=1&order=DESC&orderby=price

Here is a function:

public function get_products_list_callback( \WP_REST_Request $request ) {
    $params = $request->get_params();

    $category = General_Helper::get_array_value( 'category', $params );
    $filters  = General_Helper::get_array_value( 'filter', $params );
    $per_page = General_Helper::get_array_value( 'per_page', $params );
    $offset   = General_Helper::get_array_value( 'offset', $params );
    $order    = General_Helper::get_array_value( 'order', $params );
    $orderby  = General_Helper::get_array_value( 'orderby', $params );

    $output = [];

    // Use default arguments.
    $args = [
      'post_type'      => Config::POST_TYPE_SLUG_PRODUCT,
      'posts_per_page' => get_option( 'posts_per_page' ),
      'post_status'    => 'publish',
      'paged'          => 1,
    ];

    // Posts per page.
    if ( ! empty( $per_page ) ) {
      $args['posts_per_page'] = $per_page;
    }

    // Pagination, starts from 1.
    if ( ! empty( $offset ) ) {
      $args['paged'] = $offset;
    }

    // Order condition. ASC/DESC.
    if ( ! empty( $order ) ) {
      $args['order'] = $order;
    }

    // Orderby condition. Name/Price.
    if ( ! empty( $orderby ) ) {
      if ( $orderby === 'price' ) {
        $args['orderby'] = 'meta_value_num';
      } else {
        $args['orderby'] = $orderby;
      }
    }

    // If filter buy category or attributes.
    if ( ! empty( $category ) || ! empty( $filters ) ) {
      $args['tax_query']['relation'] = 'AND';

      // Category filter.
      if ( ! empty( $category ) ) {
        $args['tax_query'][] = [
          'taxonomy' => Config::TAXONOMY_SLUG_PRODUCT,
          'field'    => 'slug',
          'terms'    => [ $category ],
        ];
      }

      // Attributes filter.
      if ( ! empty( $filters ) ) {
        foreach ( $filters as $filter_key => $filter_value ) {
          if ( $filter_key === 'min_price' || $filter_key === 'max_price' ) {
            continue;
          }

          $args['tax_query'][] = [
            'taxonomy' => $filter_key,
            'field'    => 'term_id',
            'terms'    => \explode( ',', $filter_value ),
          ];
        }
      }

      // Min / Max price filter.
      if ( isset( $filters['min_price'] ) || isset( $filters['max_price'] ) ) {
        $price_request = [];

        if ( isset( $filters['min_price'] ) ) {
          $price_request['min_price'] = $filters['min_price'];
        }

        if ( isset( $filters['max_price'] ) ) {
          $price_request['max_price'] = $filters['max_price'];
        }

        $args['meta_query'][] = \wc_get_min_max_price_meta_query( $price_request );
      }
    }

    $the_query = new \WP_Query( $args );

    if ( ! $the_query->have_posts() ) {
      return $output;
    }

    while ( $the_query->have_posts() ) {
      $the_query->the_post();

      $output[] = get_the_title();
    }
    wp_reset_postdata();

    return $output;
  }

Hope it helps




回答2:


I just looked into the woocommerce rest api implementation at

plugins/woocommerce/includes/api/class-wc-rest-products-controller.php

file but unfortunately their codes doesn't support multiple attributes. But you can write your own query to achieve your goal.

$args = array(
'post_type' => 'product',
'tax_query' => array(
    array(
        'relation' => 'AND',
        array(
            'taxonomy' => 'pa_color',
            'field'    => 'term_id',
            'terms'    => array( 'red' ),
        ),
        array(
            'taxonomy' => 'pa_size',
            'field'    => 'term_id',
            'terms'    => array( 'Long' ),
        ),
    ),
),
);
$products = new WP_Query( $args );
print_r($products);



回答3:


Try to request like this:

products?attribute=pa_color&attribute_term=51,50&per_page=100

Its worked for me. Latest woocommerce-api wc/v2!



来源:https://stackoverflow.com/questions/49006417/woocommerce-rest-api-query-products-by-multiple-attributes

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!