如何使用WooCommerce检索cart_item_data?

25

add_to_cart 函数期间,有一个用于添加 “购物车商品数据” 的过滤器。该过滤器为 woocommerce_add_cart_item_data。我希望将我的自定义插件数据存储在其中,以便相对于商品存储数据,并且可以添加具有不同数据的多个产品。

这似乎都起作用了,但是我无法检索数据。我无法弄清楚。 数据是存在的,我可以在序列化字符串中看到它,但我无法提取它。

echo '<pre>';
var_dump( WC() );

foreach( WC()->cart->get_cart() as $cart_item ) {
  var_dump( $cart_item );
  var_dump( WC()->cart->get_item_data( $cart_item ) );
}
echo '</pre>';

WC()的第一次转储具有属性:session->_data->cart->(序列化数据)。然而,_data属性是受保护的,但我可以在序列化数据中看到我的自定义字段。

$cart_item是一个带有product_id和其他一些数据的数组,但它不包括我的自定义数据:(

最后,使用get_item_data()方法,我以为我已经想通了。我传递了购物车项目对象,结果得到一个空字符串。如果我传递密钥而不是购物车项目本身,情况也是一样的。

我应该如何访问购物车项目数据?


这是“添加购物车项目数据”的函数,它有效(或者至少看起来是有效的):

function save_class_menu_selection( $cart_item_data, $product_id, $variation_id ) {
  if ( !product_is_class( $product_id ) ) return $cart_item_data;

  // Save the date, or give a fatal warning. Date is required.
  if ( !empty($_REQUEST['class-date']) ) {
    $cart_item_data['class-date'] = stripslashes($_REQUEST['class-date']);
    return $cart_item_data;
  }else{
    wp_die('<h2>Invalid Class Date Selected</h2><p>You tried to add a class to your cart, but the date selected was invalid. Please try again.</p>');
    exit;
  }
}
add_filter( 'woocommerce_add_cart_item_data', 'save_class_menu_selection', 10, 3 );
2个回答

55

今天我也遇到了同样的情况,在一些研究之后,我进行了一些反向工程,并想为可能也会遇到这个问题的其他人提供解决方案。

问题在于购物车项从会话中恢复时,数据被清理。因此,额外的购物车项数据已存储到会话中,但在下一个请求中,它不会被恢复。

有一个“woocommerce_get_cart_item_from_session”过滤器。作为第一个参数,您会得到经过消毒的购物车项目(没有额外数据),作为第二个参数,您会得到所有存储在会话中的数据(包括额外数据)。

解决方案是钩入其中并恢复自定义购物车项数据。

示例代码:

add_filter( 'woocommerce_add_cart_item_data', function ( $cartItemData, $productId, $variationId ) {
    $cartItemData['myCustomData'] = 'someCustomValue';

    return $cartItemData;
}, 10, 3 );

add_filter( 'woocommerce_get_cart_item_from_session', function ( $cartItemData, $cartItemSessionData, $cartItemKey ) {
    if ( isset( $cartItemSessionData['myCustomData'] ) ) {
        $cartItemData['myCustomData'] = $cartItemSessionData['myCustomData'];
    }

    return $cartItemData;
}, 10, 3 );

要在购物车/结账页面上显示数据,您可以使用以下代码:

add_filter( 'woocommerce_get_item_data', function ( $data, $cartItem ) {
    if ( isset( $cartItem['myCustomData'] ) ) {
        $data[] = array(
            'name' => 'My custom data',
            'value' => $cartItem['myCustomData']
        );
    }

    return $data;
}, 10, 2 );

现在最后一步就是在订单生成时保存数据:

add_action( 'woocommerce_add_order_item_meta', function ( $itemId, $values, $key ) {
    if ( isset( $values['myCustomData'] ) ) {
        wc_add_order_item_meta( $itemId, 'myCustomData', $values['myCustomData'] );
    }
}, 10, 3 );
您不需要做任何其他事情来展示后端中的数据,所有订单项元数据都会自动显示。

1
谢谢你的回复,Stefan。听起来这与WordPress中的“查询变量”非常相似。也就是说,除非你明确告诉WordPress这样做,否则通过POST/GET传递的任何数据都不会被注册为查询变量。你知道当购物车数据转换为订单时,这些会话数据是否会被保存吗?(例如,当进行付款时) - Radley Sustaire
1
数据不会自动保存,但我已经在我的答案中添加了一些代码示例来说明如何实现。 - Stefan
我将把这个作为被接受的答案,因为我的解决方案是一个变通方法。这看起来更加适当地实现了。不过,我自己还没有测试过它。 - Radley Sustaire
这个回答非常有帮助!感谢您抽出时间发表。您能否说明如何在客户付款电子邮件中显示此自定义数据? - dcolumbus
这真的很有帮助。现在我正在尝试弄清楚如何根据自定义值更改项目价格。有人感兴趣帮忙吗? - aslamdoctor
显示剩余2条评论

5
很遗憾,我无法使默认购物车项目数据正常工作。 我觉得它可能没有正确实现,甚至可能已过时,因为缺乏支持和文档。
相反,我使用了一个购物车会话变量来实现同样的功能。 它只是一个数组,其中每个键都是cart_item_key。每个数组的值又是一个包含自定义字段的键值对数组。因此它本质上与内置的购物车项目数据相同,只是存储为购物车会话数据而已。
这里有一个Gist,其中包含一些实用程序函数,使其变得容易:

https://gist.github.com/RadGH/e3444fc661554a0f8c6f


如果你想自己构建它,关键在于WC()->session。以下是使其正常工作的两个关键函数:
WC()->session->get('_my_cart_item_data');
WC()->session->set('_my_cart_item_data', $cart_item_data_array);

这些是您需要的操作挂钩:

<<<EXAMPLES
action: woocommerce_add_to_cart
desc: When an item is added to the cart. 
args: $cart_item_key, $product_id, $quantity, $variation_id, $variation, $cart_item_data

action: woocommerce_add_order_item_meta
desc: When a cart item is converted to an order item, save metadata to the order item
      using the function "wc_add_order_item_meta( $item_id, $key, $value )"
args: item_id, $values, $cart_item_key

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接