Cannot fetch posts with certain ‘product_cat’. WP_Query is empty

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.