You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WooCommerce中动态添加现有产品属性并全选术语的PHP问题

问题分析与解决方案

问题描述

需要通过编程将现有属性添加到产品属性中并全选所有术语以生成产品变体。调用wc_get_product_attribute_taxonomies能获取完整属性数组,但在函数内var_dump($attributes_data)时返回包含“Invalid taxonomy”错误的WP_Error对象。目前可添加属性,但无法将术语ID添加到$option_term_ids数组中。

错误输出

array(2) {
  [0]=>
  array(4) {
    ["name"]=>
    string(4) "size"
    ["options"]=>
    object(WP_Error)#1842 (3) {
      ["errors"]=>
      array(1) {
        ["invalid_taxonomy"]=>
        array(1) {
          [0]=>
          string(17) "Invalid taxonomy."
        }
      }
      ["error_data"]=>
      array(0) {
      }
      ["additional_data":protected]=>
      array(0) {
      }
    }
    ["visible"]=>
    int(1)
    ["variation"]=>
    int(1)
  }
  [1]=>
  array(4) {
    ["name"]=>
    string(5) "color"
    ["options"]=>
    object(WP_Error)#1841 (3) {
      ["errors"]=>
      array(1) {
        ["invalid_taxonomy"]=>
        array(1) {
          [0]=>
          string(17) "Invalid taxonomy."
        }
      }
      ["error_data"]=>
      array(0) {
      }
      ["additional_data":protected]=>
      array(0) {
      }
    }
    ["visible"]=>
    int(1)
    ["variation"]=>
    int(1)
  }
}

原代码

function add_generated_attributes_to_product_samp($product_id, $attributeNameFirst, $attributeNameSecond)
{
    global $product;
    $product = new WC_Product();

    $attributeSlugFirstFinal = 'pa_' . $attributeNameFirst . '-' .  $product_id;

    $atributeTermsFirst = get_terms(array(
        'taxonomy' => $attributeSlugFirstFinal,
        'hide_empty' => false,
    ));

    $attributeSlugSecondFinal = 'pa_' . $attributeNameSecond . '-' .  $product_id;

    $atributeTermsSecond = get_terms(array(
        'taxonomy' => $attributeSlugSecondFinal,
        'hide_empty' => false
    ));

    $attributes_data = array(
        array('name' => $attributeNameFirst,  'options' => $atributeTermsFirst, 'visible' => 1, 'variation' => 1),
        array('name' => $attributeNameSecond,  'options' => $atributeTermsSecond, 'visible' => 1, 'variation' => 1),
    );

    if (sizeof($attributes_data) > 0) {
        $attributes = array();

        foreach ($attributes_data as $key => $attribute_array) {
            if (isset($attribute_array['name']) && isset($attribute_array['options'])) {

                $taxonomy = 'pa_' . wc_sanitize_taxonomy_name($attribute_array['name']) . '-' . $product_id;

                $option_term_ids = array();

                foreach ($attribute_array['options'] as $option) {
                    if (term_exists($option, $taxonomy)) {
                        wp_set_object_terms($product_id, $option, $taxonomy, true);
                        $option_term_ids[] = get_term_by('name', $option, $taxonomy)->term_id;
                    }
                }
            }

            $attributes[$taxonomy] = array(
                'name'          => $taxonomy,
                'value'         => $option_term_ids,
                'position'      => $key + 1,
                'is_visible'    => $attribute_array['visible'],
                'is_variation'  => $attribute_array['variation'],
                'is_taxonomy'   => '1',
            );

            update_post_meta($product_id, '_product_attributes', $attributes);
        }
    }
}

add_generated_attributes_to_product_samp(292547, 'size', 'color');

错误根源

  1. 分类法名称错误:WooCommerce全局属性的分类法格式为pa_属性slug(如pa_size),错误地在分类法后添加产品ID,导致该分类法未注册,get_terms返回WP_Error。
  2. 未处理WP_Error:直接遍历$attribute_array['options'](实际是WP_Error对象),导致后续逻辑无法执行。
  3. 元数据更新时机错误:每次循环都调用update_post_meta,会覆盖之前添加的属性,最终只保留最后一个属性。
  4. 无效的产品实例:$product = new WC_Product();未传入产品ID,创建的是空白产品实例,无实际作用。

修正后的代码

function add_generated_attributes_to_product_samp($product_id, $attributeNameFirst, $attributeNameSecond)
{
    // 获取目标产品实例
    $product = wc_get_product($product_id);
    if (!$product) return;

    // 构造标准的WooCommerce属性分类法名称
    $taxonomy_first = 'pa_' . wc_sanitize_taxonomy_name($attributeNameFirst);
    $taxonomy_second = 'pa_' . wc_sanitize_taxonomy_name($attributeNameSecond);

    // 获取属性术语,先判断分类法是否存在
    $terms_first = taxonomy_exists($taxonomy_first) ? get_terms(array(
        'taxonomy' => $taxonomy_first,
        'hide_empty' => false,
    )) : array();

    $terms_second = taxonomy_exists($taxonomy_second) ? get_terms(array(
        'taxonomy' => $taxonomy_second,
        'hide_empty' => false,
    )) : array();

    $attributes_data = array(
        array(
            'name' => $attributeNameFirst,
            'taxonomy' => $taxonomy_first,
            'options' => $terms_first,
            'visible' => 1,
            'variation' => 1
        ),
        array(
            'name' => $attributeNameSecond,
            'taxonomy' => $taxonomy_second,
            'options' => $terms_second,
            'visible' => 1,
            'variation' => 1
        ),
    );

    $attributes = array();

    foreach ($attributes_data as $key => $attr) {
        // 跳过错误的术语集合
        if (is_wp_error($attr['options'])) continue;

        $taxonomy = $attr['taxonomy'];
        $option_term_ids = array();

        foreach ($attr['options'] as $term) {
            // 将术语关联到产品
            wp_set_object_terms($product_id, $term->slug, $taxonomy, true);
            $option_term_ids[] = $term->term_id;
        }

        // 构造产品属性数组
        $attributes[$taxonomy] = array(
            'name'          => $attr['name'],
            'value'         => implode('|', $option_term_ids), // WooCommerce要求用|分隔术语ID
            'position'      => $key + 1,
            'is_visible'    => $attr['visible'],
            'is_variation'  => $attr['variation'],
            'is_taxonomy'   => 1,
        );
    }

    // 统一更新产品属性元数据
    if (!empty($attributes)) {
        update_post_meta($product_id, '_product_attributes', $attributes);
        // 刷新产品缓存
        $product->save();
    }
}

add_generated_attributes_to_product_samp(292547, 'size', 'color');

关键修正点

  • 使用标准的WooCommerce属性分类法名称,移除多余的产品ID后缀。
  • 先通过taxonomy_exists检查分类法是否存在,避免get_terms返回错误。
  • 用is_wp_error判断术语集合是否有效,跳过错误数据。
  • WooCommerce的产品属性value字段需要用|分隔术语ID,而非数组。
  • 统一在循环结束后更新元数据,避免覆盖。
  • 使用wc_get_product获取有效产品实例,并调用save()刷新缓存。

内容的提问来源于stack exchange,提问作者alench

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 06:30:17