admin管理员组

文章数量:1425815

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.

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.

Share Improve this question edited Jun 13, 2019 at 20:57 Shipso asked Jun 12, 2019 at 13:50 ShipsoShipso 115 bronze badges 3
  • 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 Commented Jun 12, 2019 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 Commented Jun 12, 2019 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 Commented Jun 12, 2019 at 21:25
Add a comment  | 

1 Answer 1

Reset to default 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/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/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/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.

本文标签: phpCannot fetch posts with certain 39productcat39 WPQuery is empty