7

目标:尽管未选择变体,仍将产品添加到购物车,即删除/禁用变体字段的强制性质。

问题: WooCommerce 绝对要求在添加到购物车之前选择所有变体。

尝试:在使用各种钩子添加到购物车之前过滤掉/删除/禁用未选择的变体;woocommerce_before_calculate_totals, woocommerce_add_to_cart, woocommerce_add_cart_item,woocommerce_add_to_cart_validation

我知道这就是 WooCommerce 的工作方式以及它以这种方式工作的原因——尽管如此,我仍然需要解决方法。

如何绕过 WooCommerce 的“选择所有变体”要求,以便即使未选择所有变体,我仍可以将产品添加到购物车?

4

2 回答 2

3

1 - 您可以使用“变体”属性“非变体”属性测试后更新

对于将处理您的产品价格的属性:

  • 创建可变产品

  • 创建真正的 Woocommerce 产品属性(真正的分类法和术语)(它不适用于“在产品页面上创建”属性,因为它不会创建真正的分类法和术语)

  • 在这里,我创建了 3 个带有一些术语的属性 在此处输入图像描述

  • 在您的可变产品上,我选择了所有 3 个属性。但指定仅使用颜色和尺寸进行变化(因此颜色和变化将处理我的价格变化),而不是属性“可选”(这将是一个可选选项) 在此处输入图像描述

  • 然后,生成您的变体。你可以在这里看到我只有颜色和尺寸组合的变体,还没有关于“可选”属性的内容

  • 此外,为您的变体属性选择“默认值”。所以在前端,属性选择 HTML 输入会有一个预选选项(用户可以直接添加到购物车) 在此处输入图像描述

  • 现在我们有了我们的变体属性,在前端有预选的值

  • 但是我们仍然错过了我们的“可选”属性

  • 将以下代码添加到您的function.php或相关的(灵感,更新/刷新,并改编自此(抱歉格式化,片段也可用作gist

  • 这将处理输出可选属性的选择输入,将其保存到购物车和订购。您可以调整它以使其成为必需或不需要,使用默认值或不使用默认值,使用不同的钩子编辑 HTML 和放置。

/**
 * List available attributes on the product page in a drop-down selection
 */
function list_attributes_on_product_page() {
    global $product;
    $attributes = $product->get_attributes();

    if ( ! $attributes ) {
        return;
    }

    //from original script, but here we want to use it for variable products
    /*if ($product->is_type( 'variable' )) {
        return;
    }*/

    echo '<div style="padding-bottom:15px;">';

    foreach ( $attributes as $attribute ) {

        //If product is variable, and attribute is used for variation: woocommerce already handle this input - so it can also be used with attributes of simple products (not variables)
    if($product->is_type( 'variable' ) && $attribute['variation']) {
        continue;
    }

        //get taxonomy for the attribute - eg: Size
        $taxonomy = get_taxonomy($attribute['name']);

        //get terms - eg: small
        $options = wc_get_product_terms( $product->get_id(), $attribute['name'], array( 'fields' => 'all' ) );
        $label = str_replace('Product ', '', $taxonomy->label);
        //display select input
        ?>
        <div style="padding-bottom:8px;">
            <label for="attribute[<?php echo $attribute['id']; ?>]"><?php echo $label; ?></label>
            <br />
            <!-- add required attribute or not, handle default with "selected" attribute depending your needs -->
            <select name="attribute[<?php echo $attribute['id']; ?>]" id="attribute[<?php echo $attribute['id']; ?>]">
                <option value disabled selected>Choose an option</option>
                <?php foreach ( $options as $pa ): ?>
                    <option value="<?php echo $pa->name; ?>"><?php echo $pa->name; ?></option>
                <?php endforeach; ?>
            </select>
        </div>
        <?php
    }

    echo '</div>';
}
add_action('woocommerce_before_add_to_cart_button', 'list_attributes_on_product_page');

/**
 * Add selected attributes to cart items
 */
add_filter('woocommerce_add_cart_item_data', 'add_attributes_to_cart_item', 10, 3 );
function add_attributes_to_cart_item( $cart_item_data, $product_id, $variation_id ) {
    $attributes = $_POST['attribute'] ?? null;

    if (empty( $attributes ) ) {
        return $cart_item_data;
    }

    $cart_item_data['attributes'] = serialize($attributes);

    return $cart_item_data;
}

/**
 * Display attributes in cart
 */
add_filter( 'woocommerce_get_item_data', 'display_attributes_in_cart', 10, 2 );
function display_attributes_in_cart( $item_data, $cart_item ) {
    if ( empty( $cart_item['attributes'] ) ) {
        return $item_data;
    }

    foreach (unserialize($cart_item['attributes']) as $attributeID => $value) {
        $attribute = wc_get_attribute($attributeID);
        $item_data[] = array(
            'key'     => $attribute->name,
            'value'   => $value,
            'display' => '',
        );
    }

    return $item_data;
}

/**
 * Add attribute data to order items
 */
add_action( 'woocommerce_checkout_create_order_line_item', 'add_attributes_to_order_items', 10, 4 );
function add_attributes_to_order_items( $item, $cart_item_key, $values, $order ) {
    if ( empty( $values['attributes'] ) ) {
        return;
    }

    foreach (unserialize($values['attributes']) as $attributeID => $value) {
        $attribute = wc_get_attribute($attributeID);
        $item->add_meta_data( $attribute->name, $value );
    }
}

结果: 在此处输入图像描述

2 -插件

您还可以使用WooCommerce的 Product Add-OnsExtra Product Options (Product Addons) 等插件进行检查。除了具有属性处理价格的真实 Woocommerce 产品变体之外,这些插件还允许您在将产品添加到购物车时在产品级别添加可选字段。如果您不需要这些“可选”属性的真实产品变体,而只需要“将保存到订单行项目产品的可选字段”,那就足够了。

3 -带钩子(调整)

现在,如果你真的需要使用钩子来处理这个问题,并且你已经有了必需和可选属性的变体。因此,您为所有属性生成了所有产品变体。但最终,只有 1 个属性对价格有影响,所以许多变体的价格相同)。

您可以先尝试使用“默认”属性值来处理它。因此,仅通过更改“影响所需价格”属性,用户始终可以从属性组合中获得现有的产品变体。所以可以加入购物车。

如果由于某种原因,您不能自己预先选择默认值:仍然创建默认属性术语,并在添加到购物车之前挂钩。在那里,从 POST 变量中,您可以:

  • 找到所需的属性值,然后在您的数据库中找到相应的产品变体
  • 以编程方式将具有正确“必需”属性和默认“非必需”属性的变体添加到购物车。

问题在于可变产品:属性对于结帐过程来说无关紧要。当用户在前端选择选项(属性)时,他选择具有或不具有相应产品变体的属性组合(由管理员创建,或使用 woocommerce 助手创建)。Woocommerce 需要一个现有的产品变体(属性组合),您可以在产品页面上看到该变体,以便将某些东西添加到购物车中。这些变体在数据库中是一个自定义的 post_type “product_variation”,可以添加到购物车和订单中作为行项目。如果属性组合没有匹配的产品变体:没有可添加到购物车的内容。

于 2021-04-12T21:31:04.223 回答
3

你可以试试

add_filter('woocommerce_dropdown_variation_attribute_options_args', 'setSelectDefaultVariableOption', 10, 1);
function setSelectDefaultVariableOption($args)
{
    $default = $args['product']->get_default_attributes();
    if (count($args['options']) > 0 && empty($default)) {
        $args['selected'] = $args['options'][0];
    }
    return $args;
}
于 2021-04-14T04:33:12.977 回答