Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use custom meta data in a WC_Product_Query on Woocommerce 3

I used to use the standard wordpress WP_Query to fetch woocommerce products based on meta data. My products are tracks and have many meta columns (like genre, instrument, mood, etc). Using WP_Query I can create a meta_query based on user input from a form, that searches for products that meet the meta requirements. All of this works great.

Now I want to use wp_get_products instead of WP_Query because it is the new way of fetching products and is supposed to be more future-proof than the old way. However, I can't seem to figure out how to pass the meta_query into that function. It was announced on github that wc_get_products would support meta from version 2.8. The only info I can find on this is at the following link: https://github.com/woocommerce/woocommerce/wiki/wc_get_products-and-WC_Product_Query (very last paragraph).

I tried passing the meta_query as an array of arrays, each containing 3 key-value pairs for key, value, and compare, just like in WP_Query. I also tried to add meta as Meta: meta-field-name, which is the name of the actual fields, only the name itself without the 'meta' prefix, and some other varieties. None of these methods work though. Can anyone tell me if this 'custom parameter support' only refers to custom parameters other than meta fields, or am I doing something wrong?

like image 763
Rob Teeuwen Avatar asked Jun 29 '18 12:06

Rob Teeuwen


2 Answers

To handle product custom meta data in a WC_Product_Query (located in wp_postmeta table), it's quiet simple and works, as explained in the very last paragraph of the related documentation.

But it doesn't handle multiple values and comparison arguments like in a WP_Query, if you don't set them in the function that extend the meta_query.

For a custom product meta key like _volume to handle the volume taken by a product in m3 (cubic meters), the following code will enable that custom meta_key with a specific compare argument "bigger than":

add_filter( 'woocommerce_product_data_store_cpt_get_products_query', 'handling_custom_meta_query_keys', 10, 3 );
function handling_custom_meta_query_keys( $wp_query_args, $query_vars, $data_store_cpt ) {
    $meta_key = '_volume'; // The custom meta_key

    if ( ! empty( $query_vars[$meta_key] ) ) {
        $wp_query_args['meta_query'][] = array(
            'key'     => $meta_key,
            'value'   => esc_attr( $query_vars[$meta_key] ),
            'compare' => '>', // <=== Here you can set other comparison arguments
        );
    }
    return $wp_query_args;
}

Code goes in function.php file of the active child theme (or active theme).

Now you will just make your query on this custom _volume meta key based on the specific 'compare' argument, to get all products that have a volume bigger than '0.2':

$queried_products = wc_get_products( array( '_volume' => '0.2' ) );

Tested and works.

As you can see, you can continue using a WP_Query as many Woocommerce developers still do or even SQL queries through WordPress WPDB Class…

The announced revolution around this is not going to come soon and I suppose that they will extend WC_Product_Query and WC_Order_query like WP_Query with many more features and possibilities.

like image 50
LoicTheAztec Avatar answered Sep 29 '22 09:09

LoicTheAztec


You can add this little function to fix it all :

add_filter( 'woocommerce_product_data_store_cpt_get_products_query', static function($wp_query_args, $query_vars, $data_store_cpt){
    if ( ! empty( $query_vars['meta_query'] ) ) {$wp_query_args['meta_query'][] = $query_vars['meta_query'];}
    return $wp_query_args;
}, 10, 3 );

Now just pass meta_query to the wc_get_products and it supports it :). They probably should hire me lol.

like image 36
Steve Moretz Avatar answered Sep 29 '22 07:09

Steve Moretz