【问题标题】:Changing product name on checkout and order on WooCommerce with WPML使用 WPML 在 WooCommerce 上更改结帐和订单时的产品名称
【发布时间】:2019-05-31 08:22:58
【问题描述】:

我正在使用带有 WPML 插件的 WooCommerce。当客户在某些条件下可以升级其产品但保持旧产品价格时,我想在结帐时实施一项功能。

产品是可变的,具有许多可变属性。 因此,更具体地说,我想要的是,如果客户在结帐时选择了 x 价格的特定产品变体(在特定条件下),我可以用其他产品的变体更改他的购物车商品,但保留 x 价格。

我首先尝试的是使用woocommerce_order_item_name 钩子仅更改产品名称,但更改并未遵循订单。这很重要,因为一些订单数据随后会发送到 API。

之后我使用了 "Changing WooCommerce cart item names" 答案代码,在我安装 WPML 之前,它非常适合我的目的。出于某种原因,WC_Cart 方法 set_name() 不适用于 WPML。我打开了a support thread,但他们仍然找不到解决方案。

任何人都可以提出任何其他解决方案吗?

更新

我尝试了一种方法,即删除购物车上的产品项目,然后添加我需要的产品。在我使用 set_price() 更改新添加项目的价格之后。删除/添加似乎正在工作,但一种语言的价格没有改变,并且在下订单后也不适用于两种语言。 这是我使用的代码:

function berrytaxiplon_change_product_name( $cart ) {

if ( is_admin() && ! defined( 'DOING_AJAX' ) )
    return;

if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
    return;

    // Loop through cart items
    foreach ( $cart->get_cart() as $cart_item_key => $cart_item ) {

        // Get an instance of the WC_Product object
        $product = $cart_item['data'];

        // Get the product name (Added Woocommerce 3+ compatibility)
        $product_id = method_exists( $product, 'get_parent_id' ) ? $product->get_parent_id() : $product->post->post_parent;

        if ( ICL_LANGUAGE_CODE == 'en') {
            if (isset($cart_item['s-member-level']) && $cart_item['s-member-level'] == 3 && $product_id == 12) {

                $new_product = wc_get_product( 82 );
                $atrributes = $product->get_attributes('view');
                foreach ($atrributes as $atrribute_key => $atrribute_value) {
                    $new_attributes['attribute_' . $atrribute_key] = strtolower($atrribute_value);
                }
                $new_variation_id = find_matching_product_variation_id(82, $new_attributes);
                $cart->remove_cart_item( $cart_item_key );
                $cart->add_to_cart( 82, 1, $new_variation_id, $new_attributes, $cart_item );

                foreach ( WC()->cart->get_cart() as $new_item ) {

                    $new_item['data']->set_price( $cart_item['s-fare'] );
                }
            }
        } else {
            if (isset($cart_item['s-member-level']) && $cart_item['s-member-level'] == 3 && $product_id == 282) {

                $new_product = wc_get_product( 303 );

                $atrributes = $product->get_attributes('view');
                foreach ($atrributes as $atrribute_key => $atrribute_value) {
                    $new_attributes['attribute_' . $atrribute_key] = strtolower($atrribute_value);
                }
                $new_variation_id = find_matching_product_variation_id(303, $new_attributes);
                $cart->remove_cart_item( $cart_item_key );
                $cart->add_to_cart( 303, 1, $new_variation_id, $new_attributes, $cart_item );
                foreach ( WC()->cart->get_cart() as $new_item ) {
                    $new_item['data']->set_price( $cart_item['s-fare']);
                }

            }
        }

    }

}
add_action( 'woocommerce_before_calculate_totals', 'berrytaxiplon_change_product_name', 10, 1 );

知道为什么不应用 set_price() 方法吗?

更新 2

WPMl 使用 'woocommerce_before_calculate_totals' 并覆盖在 functions.php 上添加的操作

WPML 支持提供了一个使用 3 个过滤器的解决方案:

https://wpml.org/forums/topic/cant-use-set_name-method-for-the-product-object-on-checkout/#post-3977153

【问题讨论】:

  • 您能否详细说明“某些条件”部分。这是用户在页面加载时执行或确定的某些操作还是类似的操作?
  • 用户在结账前做出选择(跳过购物车页面,只能购买一种产品),作为项目元传递。如果此元存在并且选择了特定产品,我必须进行升级。
  • 在这种情况下,做出选择后,您可以清空购物车并添加具有自定义价格的新产品,然后再重定向到结帐。我将在几分钟后将示例代码粘贴到答案中。
  • @thepi 请注意,“寻求调试帮助的问题(“为什么这段代码不起作用?”)必须包括所需的行为、特定问题或错误 以及最短的代码有必要在问题本身中重现它。没有明确的问题陈述的问题对其他读者没有用处。请参阅:How to create a Minimal, Reproducible Example"
  • @LoicTheAztec 如果我使用了错误的问题类别,我很抱歉。在 WPML 上打开支持线程之前,我几天前已经创建(但未发布)这个问题。这个问题更多的是关于如何处理这个问题的建议。

标签: wordpress woocommerce checkout wpml


【解决方案1】:

所以这是我在我的一个项目中使用的代码,用于根据一些过滤器和所选产品将产品变体添加到购物车:

$product = new WC_Product($product_id); //The main product whose variation has to be added
$product_name = $product->get_name(); //Name of the main product
$quantity = sanitize_text_field($cData['quantity']); //You can set this to 1
$variation_id = sanitize_text_field($cData['variation_id']); //I had the variation ID from filters
$variation = array(
    'pa_duration' => sanitize_text_field($cData['duration']) //The variation slug was also available for me.
);
$cart_item_data = array('custom_price' => sanitize_text_field($custom_price));
$cart = WC()->cart->add_to_cart( (int)$product_id, (int)$quantity, (int)$variation_id, $variation, $cart_item_data ); //This will add products to cart but with the actual price of the variation being added and meta data holding the custom price.
WC()->cart->calculate_totals();
WC()->cart->set_session();
WC()->cart->maybe_set_cart_cookies();

然后您需要在计算购物车总数之前进行检查并将价格设置为自定义价格,如下所示:

function woocommerce_custom_price_to_cart_item( $cart_object ) {  
    if( !WC()->session->__isset( "reload_checkout" )) {
        foreach ( $cart_object->cart_contents as $key => $value ) {
            if( isset( $value["custom_price"] ) ) {
                $value['data']->set_price($value["custom_price"]);
            }
        }  
    }  
}
add_action( 'woocommerce_before_calculate_totals', 'woocommerce_custom_price_to_cart_item', 99 );

【讨论】:

    【解决方案2】:

    Faham 提供的代码非常有用,但导致结帐的页面模板已经过于复杂,因此我专注于在我一直在尝试的 'woocommerce_before_calculate_totals' 挂钩上使用他的逻辑。 因此,我没有尝试更改名称,而是删除了该项目并添加了新项目。然后调用一个新循环,我将价格设置为被移除的项目。

    function berrytaxiplon_change_product_name( $cart ) {
    
        if ( is_admin() && ! defined( 'DOING_AJAX' ) )
            return;
    
        if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
            return;
    
        // Loop through cart items
        foreach ( $cart->get_cart() as $cart_item_key => $cart_item ) {
    
            // Get an instance of the WC_Product object
            $product = $cart_item['data'];
    
            // Get the product name (Added Woocommerce 3+ compatibility)
            $product_id = method_exists( $product, 'get_parent_id' ) ? $product->get_parent_id() : $product->post->post_parent;
    
            if ( ICL_LANGUAGE_CODE == 'en') {
                if (isset($cart_item['s-member-level']) && $cart_item['s-member-level'] == 3 && $product_id == 12) {
                // SET THE NEW NAME
                $new_product = wc_get_product( 82 );
    
                $atrributes = $product->get_attributes('view');
                foreach ($atrributes as $atrribute_key => $atrribute_value) {
                    $new_attributes['attribute_' . $atrribute_key] = strtolower($atrribute_value);
                }
                $new_variation_id = find_matching_product_variation_id(82, $new_attributes);
                $cart->remove_cart_item( $cart_item_key );
                $cart->add_to_cart( 82, 1, $new_variation_id, $new_attributes, $cart_item );
    
                foreach ( WC()->cart->get_cart() as $new_item ) {
                    $new_item['data']->set_price( get_post_meta( $cart_item['variation_id'], '_price', true ) );
                }
    
                }
            } else {
                if (isset($cart_item['s-member-level']) && $cart_item['s-member-level'] == 3 && $product_id == 282) {
                    // SET THE NEW NAME
                    $new_product = wc_get_product( 303 );
    
                    $atrributes = $product->get_attributes('view');
                    foreach ($atrributes as $atrribute_key => $atrribute_value) {
                        $new_attributes['attribute_' . $atrribute_key] = strtolower($atrribute_value);
                    }
                    $new_variation_id = find_matching_product_variation_id(303, $new_attributes);
                    $cart->remove_cart_item( $cart_item_key );
                    $cart->add_to_cart( 303, 1, $new_variation_id, $new_attributes, $cart_item );
                    foreach ( WC()->cart->get_cart() as $new_item ) {
                        $new_item['data']->set_price( get_post_meta( $cart_item['variation_id'], '_price', true ) );
                    }
    
                   }
            }
    
        }
    }
    add_action( 'woocommerce_before_calculate_totals', 'berrytaxiplon_change_product_name', 10, 1 );  
    

    我使用下面的函数来匹配取自问题WooCommerce: Get Product Variation ID from Matching Attributes的属性

    function find_matching_product_variation_id($product_id, $attributes)
    {
        return (new \WC_Product_Data_Store_CPT())->find_matching_product_variation(
            new \WC_Product($product_id),
            $attributes
        );
    }
    

    我对在 $cart_item 中使用 add_to_cart() 和第二个 foreach() 持怀疑态度。但我测试过,它似乎可以正常工作。

    更新

    实际上,此代码(或再次使用 WPML)存在问题。似乎 set_price() 不适用于辅助语言。但是,如果我重新加载结帐页面并再次发送数据,则会应用新价格。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-08-19
      • 2021-07-21
      • 2018-06-22
      • 2012-08-10
      • 1970-01-01
      • 2019-03-31
      相关资源
      最近更新 更多