当前位置: 首页 > 知识库问答 >
问题:

Woocommerce以编程方式添加产品属性及其相应的值

杨超
2023-03-14

我正在构建一个获取产品的脚本,而我被困在以编程方式添加属性的部分。所以基本上我想检查属性是否存在,如果不存在,就添加它。然后检查它的价值是否存在,如果不存在,则添加它的价值,并将所有内容附加到我的产品上。

以下是我获得产品的格式

 [attributes] => Array
(
[0] => stdClass Object
    (
        [id] => 332
        [name] => Gender
        [value] => Woman
    )

[1] => stdClass Object
    (
        [id] => 333
        [name] => Wheel Size
        [value] => 28 Inch
    )

[2] => stdClass Object
    (
        [id] => 334
        [name] => Frame height
        [value] => 56 cm
    )

现在我已经尝试了两个版本,我将粘贴两个代码示例。

第1版:

foreach($product->attributes as $attribute) {
$slug = 'pa_' . strtolower($attribute->name);
$attribute_name = $attribute->name;
$attribute_value = $attribute->value;

$permalinks = get_option( 'woocommerce_permalinks' );

$taxonomy_data = array(
                    'hierarchical'          => true,
                    'update_count_callback' => '_update_post_term_count',
                    'labels'                => array(
                            'name'              => $attribute_name
                        ),
                    'show_ui'           => false,
                    'query_var'         => true,
                    'sort'              => false,
                    'public'            => true,
                    'show_in_nav_menus' => false,
                    'capabilities'      => array(
                        'manage_terms' => 'manage_product_terms',
                        'edit_terms'   => 'edit_product_terms',
                        'delete_terms' => 'delete_product_terms',
                        'assign_terms' => 'assign_product_terms',
                    )
                );

register_taxonomy( $slug, array('product'), $taxonomy_data );
// @end_Debug

}

这个版本只添加了附加到产品的属性,但是在Wordpress管理的属性选项卡下不可见。我以后会想要这些属性的过滤器,所以我需要与WooCommerce属性的连接。

第2版:

foreach($product->attributes as $attribute) {
$slug = 'pa_' . strtolower($attribute->name);
$attribute_name = $attribute->name;
$attribute_value = $attribute->value;
$table = $wpdb->prefix . 'woocommerce_attribute_taxonomies';

$attr = $wpdb->get_results( "SELECT * FROM {$table} WHERE attribute_name LIKE '%{$attribute_name}%'", OBJECT );
if(count($attr) > 0) {
    //
}
else {
    /** create taxonomy */
    $data = array(
        'attribute_label'   => $attribute_name,
        'attribute_name'    => $slug,
        'attribute_type'    => 'select',
        'attribute_orderby' => 'menu_order',
        'attribute_public'  => 0, // Enable archives ==> true (or 1)
    );

    $results = $wpdb->insert( "{$wpdb->prefix}woocommerce_attribute_taxonomies", $data );

    if ( is_wp_error( $results ) ) {
        return new WP_Error( 'cannot_create_attribute', $results->get_error_message(), array( 'status' => 400 ) );
    }

    $id = $wpdb->insert_id;

    do_action('woocommerce_attribute_added', $id, $data);

    wp_schedule_single_event( time(), 'woocommerce_flush_rewrite_rules' );
    /* end_Create */
}


// Clean attribute name to get the taxonomy
$taxonomy = 'pa_' . wc_sanitize_taxonomy_name( $attribute_name );

$option_term_ids = array(); // Initializing

// Loop through defined attribute data options (terms values)
if( term_exists( $attribute_value, $taxonomy ) ){
    // Save the possible option value for the attribute which will be used for variation later
    wp_set_object_terms( $product_id, $attribute_value, $taxonomy, true );
    // Get the term ID
    $option_term_ids[] = get_term_by( 'name', $attribute_value, $taxonomy )->term_id;
}

    // Loop through defined attribute data
$attributes[$taxonomy] = array(
    'name'          => $taxonomy,
    'value'         => $option_term_ids, // Need to be term IDs
    'position'      => '1',
    'is_visible'    => '1',
    'is_variation'  => '1',
    'is_taxonomy'   => '1'
);

// Save the meta entry for product attributes
update_post_meta( $product_id, '_product_attributes', $attributes );

}

这一个似乎只在产品属性标签下添加它们,也没有添加术语值。

共有1个答案

向子安
2023-03-14

好吧,这是一个相当复杂的任务,但这是我通过查看别人的源代码并根据需要进行修改而得到的代码。

首先,您需要这些助手函数。

>

  • 要创建全局属性,您需要使用以下函数为每个属性(性别、车轮大小等)创建一个分类法:

    function create_global_attribute($name, $slug)
    {
    
        $taxonomy_name = wc_attribute_taxonomy_name( $slug );
    
        if (taxonomy_exists($taxonomy_name))
        {
            return wc_attribute_taxonomy_id_by_name($slug);
        }
    
        //logg("Creating a new Taxonomy! `".$taxonomy_name."` with name/label `".$name."` and slug `".$slug.'`');
    
        $attribute_id = wc_create_attribute( array(
            'name'         => $name,
            'slug'         => $slug,
            'type'         => 'select',
            'order_by'     => 'menu_order',
            'has_archives' => false,
        ) );
    
        //Register it as a wordpress taxonomy for just this session. Later on this will be loaded from the woocommerce taxonomy table.
        register_taxonomy(
            $taxonomy_name,
            apply_filters( 'woocommerce_taxonomy_objects_' . $taxonomy_name, array( 'product' ) ),
            apply_filters( 'woocommerce_taxonomy_args_' . $taxonomy_name, array(
                'labels'       => array(
                    'name' => $name,
                ),
                'hierarchical' => true,
                'show_ui'      => false,
                'query_var'    => true,
                'rewrite'      => false,
            ) )
        );
    
        //Clear caches
        delete_transient( 'wc_attribute_taxonomies' );
    
        return $attribute_id;
    }
    

    现在将这些应用到您的产品中,我假设您使用的是可变产品,每个产品都有变化?父变量产品需要将其属性属性设置为特殊格式的属性数组。此函数用于创建该数组,如果未找到每个属性,则为其创建全局分类。

    //$rawDataAttributes must be in the form of array("Color"=>array("blue", "red"), "Size"=>array(12,13,14),... etc.)
    function generate_attributes_list_for_product($rawDataAttributes)
    {
        $attributes = array();
    
        $pos = 0;
    
        foreach ($rawDataAttributes as $name => $values)
        {
            if (empty($name) || empty($values)) continue;
    
            if (!is_array($values)) $values = array($values);
    
            $attribute = new WC_Product_Attribute();
            $attribute->set_id( 0 );
            $attribute->set_position($pos);
            $attribute->set_visible( true );
            $attribute->set_variation( true );
    
            $pos++;
    
            //Look for existing attribute:
            $existingTaxes = wc_get_attribute_taxonomies();
    
            //attribute_labels is in the format: array("slug" => "label / name")
            $attribute_labels = wp_list_pluck( $existingTaxes, 'attribute_label', 'attribute_name' );
            $slug = array_search( $name, $attribute_labels, true );
    
            if (!$slug)
            {
                //Not found, so create it:
                $slug = wc_sanitize_taxonomy_name($name);
                $attribute_id = create_global_attribute($name, $slug);
            }
            else
            {
                //Otherwise find it's ID
                //Taxonomies are in the format: array("slug" => 12, "slug" => 14)
                $taxonomies = wp_list_pluck($existingTaxes, 'attribute_id', 'attribute_name');
    
                if (!isset($taxonomies[$slug]))
                {
                    //logg("Could not get wc attribute ID for attribute ".$name. " (slug: ".$slug.") which should have existed!");
                    continue;
                }
    
                $attribute_id = (int)$taxonomies[$slug];
            }
    
            $taxonomy_name = wc_attribute_taxonomy_name($slug);
    
            $attribute->set_id( $attribute_id );
            $attribute->set_name( $taxonomy_name );
            $attribute->set_options($values);
    
            $attributes[] = $attribute;
        }
    
    
        return $attributes;
    }
    

    我们几乎已经准备好将属性应用于产品,但是主要变量Product及其变体需要像任何Wordpress分类法一样将分类法术语分配给它们。因此,如果您有一个名为“Wheel Size”的分类法,其中有“28英寸”和“30英寸”两个术语,那么父产品需要将所有“28英寸”和“30英寸”术语分配给它,并且变体需要将各自的术语分配给它们,因此一个术语为“28英寸”,另一个术语为“30英寸”。为了对此有所帮助,我们使用此函数获取和/或创建这些不存在的术语:

    function get_attribute_term($value, $taxonomy)
    {
        //Look if there is already a term for this attribute?
        $term = get_term_by('name', $value, $taxonomy);
    
        if (!$term)
        {
            //No, create new term.
            $term = wp_insert_term($value, $taxonomy);
            if (is_wp_error($term))
            {
                //logg("Unable to create new attribute term for ".$value." in tax ".$taxonomy."! ".$term->get_error_message());
                return array('id'=>false, 'slug'=>false);
            }
            $termId = $term['term_id'];
            $term_slug = get_term($termId, $taxonomy)->slug; // Get the term slug
        }
        else
        {
            //Yes, grab it's id and slug
            $termId = $term->term_id;
            $term_slug = $term->slug;
        }
    
        return array('id'=>$termId, 'slug'=>$term_slug);
    }
    

    好的,最后,我们可以使用上面的内容将属性应用到我们的产品中。

    对于主要变量产品:

    $yourRawAttributeList = array("Gender" => array("Woman", "Man"), "Wheel Size" => array("28 Inch","30 Inch","32 Inch"));
    $attribs = generate_attributes_list_for_product($yourRawAttributeList);
    
    $p = new WC_Product_Variable($postID);
    
    $p->set_props(array(
        'attributes'        => $attribs,
        //Set any other properties of the product here you want - price, name, etc.
    ));
    
    $postID = $p->save();
    
    if ($postID <= 0) return "Unable to create / update product!";
    
    //Attribute Terms: These need to be set otherwise the attributes dont show on the admin backend:
    foreach ($attribs as $attrib)
    {
        /** @var WC_Product_Attribute $attrib */
        $tax = $attrib->get_name();
        $vals = $attrib->get_options();
    
        $termsToAdd = array();
    
        if (is_array($vals) && count($vals) > 0)
        {
            foreach ($vals as $val)
            {
                //Get or create the term if it doesnt exist:
                $term = get_attribute_term($val, $tax);
    
                if ($term['id']) $termsToAdd[] = $term['id'];
            }
        }
    
        if (count($termsToAdd) > 0)
        {
            wp_set_object_terms($postID, $termsToAdd, $tax, true);
        }
    }
    

    对于该产品的每个变体:

        //This is an array of input attributes in the form: array("Color"=>"Navy", "Size"=>"25")
    $theseAttributes = array("Gender" => array("Woman"), "Wheel Size" => array("28 Inch"));
    
    //This is the final list of attributes that we are calculating below.
    $theseAttributesCalculated = array();
    
    //logg("Want to add these attributes to the variation: ".print_r($theseAttributes, true));
    
    $existingTax = wc_get_attribute_taxonomies();
    
    foreach ($theseAttributes as $name => $value)
    {
        if (strlen($name) == 0 || strlen($value) == 0)
        {
            //logg("Attribute array had a blank value for product variant ".$sku.': '.print_r($theseAttributes, true));
            return "Attribute array had a blank value.";
        }
    
        $tax = '';
        $slug = '';
    
        //Look for an existing taxonomy to match this attribute's $name
        //$thistax->attribute_name = slug of the taxonomy
        //$thistax->attribute_label = name of the taxonomy
    
        foreach ($existingTax as $thistax)
        {
            if ($thistax->attribute_label == $name)
            {
                $slug = $thistax->attribute_name;
                $tax = wc_attribute_taxonomy_name($slug);
                break;
            }
        }
    
        if (empty($tax))
        {
            $slug = wc_sanitize_taxonomy_name($name);
            //Taxonomy not found, so create it...
            if (create_global_attribute($name, $slug) > 0)
            {
                $tax = wc_attribute_taxonomy_name($slug);
            }
            else
            {
                //logg("Unable to create new attribute taxonomy ".$slug." for attribute ".$name."found in variable product ".$sku);
                continue;
            }
        }
    
    
        //logg("Want to add attribute ".$name. " value ".$value. " which is term ".$term_slug." (".$termId.") to post ".$parentID);
    
        $term = get_attribute_term($value, $tax);
    
    
        if ($term['id'])
        {
            // Set/save the attribute data in the product variation
            $theseAttributesCalculated[$tax] = $term['slug'];
        }
        else
        {
            //logg("Warning! Unable to create / get the attribute ".$value." in Taxonomy ".$tax);
        }
    }
    
    //logg("Finished gathering. Results: ".print_r($theseAttributesCalculated, true));
    
    
    $variation  = new \WC_Product_Variation($postID);
    
    $variation->set_props( array(
        'attributes'        => $theseAttributesCalculated,
    ));
    
    $postID = $variation->save();
    
    if ($postID <= 0) return "Unable to create product variation!";
    

  •  类似资料:
    • 我试图以编程方式批量添加WooCommerce中的产品,但出于某种原因,它只是添加了第一个产品。我正在向一个应用程序发出请求,该应用程序返回带有产品名称和描述的JSON响应。到目前为止,我的代码看起来像下面的代码:

    • 如何从插件为WooCommerce创建属性?我只发现: 从这个问题 但这种方法需要某些产品的id。我需要生成一些未附加到任何产品的属性。

    • 我正在使用在woocommerce中以编程方式添加产品。除了产品属性外,其他所有功能都正常工作。除非我从管理员处单击“更新”,否则产品页面视图中不会显示产品属性。 我正在添加成吨的产品,所以有没有办法在产品页面的下拉列表中显示变化。 这是我的代码,它工作正常,所有内容都放在正确的字段中,如果不单击“更新”,它就不会在产品页面上显示选项。

    • 每次根据其他几个字段的内容保存产品时,我都希望更新产品在我的商店中的属性。 然而,我正在努力让我的属性正确出现。 最初,我试图使用以下功能根据这个问题的公认答案更新产品: 这将添加到了分类法的可用术语列表中,但在我检查产品属性时,它们不可见。 接下来,我尝试了上述问题中第二个答案的变体: 这也无法更新产品的属性。 在这一点上,我不知道下一步该尝试什么。使用操作似乎是有效的,因为这个术语确实被添加到

    • 我在WooCommerce版本3+中创建了一个可变产品(父“产品”)。从一个WordPress插件中,我想以编程方式创建具有新属性值的产品变体(儿童“产品)。 变体属性已在WooCommerce中设置。 因此,每次创建一个变体时,都应以编程方式创建新属性的值,并在父变量product中设置新属性的值。 如何才能做到这一点呢?有可能吗? 更新:我已经为此编写了更多的代码行,并且尝试了许多方法来解决它

    • 我正在使用此代码添加自定义属性 这个代码的结果我得到了添加只是产品属性名称没有术语值... 我找了很多,但没有得到任何答案。