0

I want to set attributes for woocommerce products in certain product category. The query, however, doesn't seem to work.

I've placed the following code into functions.php of my child-theme. Tried replacing slug by term_id, tried adding 'relation', just in case, tried to set the slug explicitly instead of variable, but still no luck.

function wccategory_set_attributes($categoryslug, $attributes) {
    $pquery = new WP_Query( array(
        'post_type'   => 'product',
        'post_status' => 'publish',
        'posts_per_page' => 10,
        'tax_query'   => array(
            array(
                'taxonomy' => 'product_cat',
                'field'    => 'slug',
                'terms'    => $categoryslug,
            ),
        ),
    ));

    if( $pquery->have_posts() ) { //that condition is never true with tax_query
        while ($pquery->have_posts()) : $pquery->the_post();
            foreach ($attributes as $name => $value) {
                wp_set_object_terms( $postid, $value, $name, false );
                $product_attributes[$i] = array (
                    'name' => htmlspecialchars( stripslashes( $name ) ),
                    'value' => $value,
                    'is_visible' => 1,
                    'is_taxonomy' => 0
                );
                $i++;
            }
            update_post_meta( $postid,'_product_attributes', $product_attributes); 
        endwhile;
    }
}
wccategory_set_attributes('theslug', array ( 'pa_length' => '', 'pa_width' => '', 'pa_type' => ''));

$pquery->have_posts() returns nothing. The posts are present, though. Once I remove 'tax_query' from arguments, all works. I assume, that there is some error in 'tax_query'. I looked many other examples, including WPCodex WP_Query reference. It looks fine, but it seems I'm missing something. The version of WooCommerce I am using is 3.5.7.

  • Where are you running this code? If the last line isn't running after the init hook, then there might be issues if the taxonomy hasn't been registered yet. – Jacob Peattie Jun 12 at 14:29
  • Can you drop a echo $categoryslug; die();' in right before your $pquery = new WP_Query( array( call and see what that echos back?? Just want to make sure you have a slug there :) – ChristopherJones Jun 12 at 14:56
  • I am running this code in functions.php of my child-theme. echo $categoryslug; die(); echoes 'theslug', exactly what was given in function call. – Shipso Jun 12 at 21:25
0

This answer assumes you are using WooCommerce version 3.0 or newer.

Below is your function modified to use the new CRUD objects in WooCommerce. This is the way to edit products and add data to products in the newer versions of WooCommerce. We use wc_get_products() to get an array of product objects, this function takes various parameters, for all the options you can check out https://github.com/woocommerce/woocommerce/wiki/wc_get_products-and-WC_Product_Query. To see what setters exist on the product object you can check out https://docs.woocommerce.com/wc-apidocs/class-WC_Product.html.

We also use the WC_Product_Attribute object for creating the attributes. More information can be found here https://docs.woocommerce.com/wc-apidocs/class-WC_Product_Attribute.html.

See comments for explanation of what the function does

function wccategory_set_attributes($categoryslug, $attributes) {
    // Get any products in the category matching the slug we pass in
    $products = wc_get_products(array(
        'status' => 'publish',
        'category' => array($categoryslug),
    ));

    // Loop the products
    foreach($products as $product) {
        $product_attributes = array();
        foreach($attributes as $key => $val) {
            // Create a new attribute for each of the attributes we have passed to the function
            $new_attribute = new WC_Product_Attribute();

            // If attribute exists globally we set the correct attribute id
            $new_attribute->set_id(wc_attribute_taxonomy_id_by_name($key));
            $new_attribute->set_name($key);

            // Because we cast to array you can choose to pass in an array of values/options for the attribute
            $new_attribute->set_options((array)$val);
            $new_attribute->set_visible(1);
            $new_attribute->set_variation(0);

            $product_attributes[] = $new_attribute;
        }

        // Set the attributes on the product object
        $product->set_attributes($product_attributes);

        // Store the product
        $product->save();
    }
}

Calling the function(Assumes you have a product category with slug "theslug")

wccategory_set_attributes('theslug', array('pa_length' => '', 'pa_width' => ''));

When calling the function there are numerous things to consider. If the attribute has not been created globally(Meaning they dont exists under Products -> Attributes in WooCommerce), prefixing the attributes with "pa_" will include the "pa_" in the attribute name. You may not want that and you can replace "pa_length" with "Length" and so on. Like this:

wccategory_set_attributes('theslug', array('Length' => '', 'Width' => ''));

When including no options for the attributes it will remove any options that exist for this product. If you want to include options you can either include one option for each by passing a single value or you can pass in an array of options. The two examples are shown below:

Option 1

wccategory_set_attributes('theslug', array('pa_length' => '100', 'pa_width' => '500'));

Option 2

wccategory_set_attributes('theslug', array('pa_length' => array('100', '200'), 'pa_width' => array('500', '1000')));

"type" is a reserved taxonomy name therefore you cannot create "pa_type" globally. You can however create a product attribute called "Type" locally on the product.

  • Thank you very much for useful information. However, the main problem with empty query persists. It seems that something is seriously wrong, as wc_get_products() doesn't return anything at all, with any arguments given. Tried: $products = wc_get_products(array( 'status' => 'publish', )); echo count($products); die(); and $query = new WC_Product_Query(array( 'status' => 'publish', )); $products = $query->get_products(); echo count($products); die(); Both variants echo 0 The version of WooCommerce I am using is 3.5.7. – Shipso Jun 13 at 20:53
  • Does it work when you provide it 0 arguments? – Alex Uleberg Jun 14 at 6:57
  • No, it doesn't work even without arguments. That's what I meant by "something is seriously wrong". – Shipso Jun 14 at 7:19
  • Then there must be something wrong somewhere else. If product queries return no products. Have you double checked that the products are in there and that they are published? If they are i would suggest disabling all plugins and switching to the storefront theme to see if the problem still persists. – Alex Uleberg Jun 17 at 12:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.