In the previous post, I’ve shown you how to filter WordPress posts and custom post types by a meta field value using WP REST API. Some of you might think that this method can be used for the WooCommerce custom post types too (products, orders, etc.). Although they are the custom post types too, WooCommerce uses its own REST API endpoints. You can learn more about the WooCommerce REST API in the official documentation.
Earlier, we used the rest_{$this->post_type}_query filter hook to pass our custom arguments to a posts query based on the provided query parameters. This hook doesn’t work with the WooCommerce custom post types, but, luckily, we can still filter products or orders by a meta field using a similar filter hook.
How to filter WooCommerce products by a meta field?
We’ll start with the most important post type in WooCommerce. Let’s imagine that our products have a custom meta field — Brand. And we want to get all products belonging to a certain brand using WooCommerce REST API. How can we do this?
For example, I want to get all products with the Brand meta field equal to Nike. How can I achieve this using WooCommerce REST API?
As I said earlier, the rest_{$this->post_type}_query filter hook doesn’t get triggered when you use the WooCommerce REST API endpoints. Luckily, the WooCommerce developers have added a very similar filter hook —woocommerce_rest_{$this->post_type}_object_query.
As you might have guessed, all you need to do is to change {$this->post_type} to the post type’s slug you need. Since we want to filter WooCommerce products, we’ll need to use the woocommerce_rest_product_object_query filter hook. This hook passes two arguments to its handlers: $args and $request. We can modify the WP_Query arguments using the first argument, and we can access the request parameters using the last one.
I guess you got the idea. Especially, if you’ve already experimented with my previous tutorial. Let’s write some code:
add_filter( 'woocommerce_rest_product_object_query', 'filter_products_by_brand_field', 999, 2 );
function filter_products_by_brand_field( $args, $request ) {
if ( ! isset( $request['brand'] ) ) {
return $args;
}
$source_value = sanitize_text_field( $request['brand'] );
$source_meta_query = array(
'key' => 'brand',
'value' => $source_value
);
if ( isset( $args['meta_query'] ) ) {
$args['meta_query']['relation'] = 'AND';
$args['meta_query'][] = $source_meta_query;
} else {
$args['meta_query'] = array();
$args['meta_query'][] = $source_meta_query;
}
return $args;
}
Now, a GET request to the following URL: https://mywebshop.com/wp-json/wc/v3/products?brand=Nike, will return an array of products which brand meta field equals to “Nike”. If there are no products matching this requirement, WooCommerce REST API will return an empty array.
How to use this filter hook with other WooCommerce post types?
The best part of this hook is that you can use the same logic for all WooCommerce post types. As I said, all you need to do is to pass the slug of the post type you want to filter instead of the {$this->post_type}. For example:
- Use woocommerce_rest_shop_order_object_query hook to filter WooCommerce orders
- Use woocommerce_rest_shop_coupon_object_query hook to filter WooCommerce coupons
- Use woocommerce_rest_product_variation_object_query hook to filter WooCommerce variations
You can learn more about the WooCommerce custom post types in the WooCommerce documentation. In all cases, your hook handlers will receive two arguments: $args (an array of the WP_Query arguments defined before) and $request (a WP_REST_Request instance which allows you to access a request’s parameters).
Summary
As you see, this method almost completely repeats the one we used to filter regular WordPress post types. There is no surprise, though, given that WooCommerce belongs to Automattic — the company behind WordPress.
Anyways, I hope this post you found this post helpful for you and your project. If you have any other questions about WooCommerce REST API or want me to describe a topic you’re interested in — let me know about this in the comments section below.
Thank you for reading this post; see you in the next one!