Как получить cart_item_data с помощью WooCommerce?
Во время 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->(serialized data)
. Однако свойство _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 );
Ответы
Ответ 1
Сегодня я был в той же ситуации и наткнулся на этот вопрос после некоторых исследований.
После некоторой обратной инженерии я нашел проблему и хочу предложить решение для других, которые могут также наткнуться на этот вопрос.
Проблема в том, что данные дезинфицируются, когда элементы корзины восстанавливаются из сеанса. Таким образом, дополнительные данные элемента корзины хранятся в сеансе, но при следующем запросе он не восстанавливается.
Имеется фильтр "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 );
Чтобы также показать данные на странице cart/checkout, вы можете использовать следующий код:
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 );
Вам не нужно ничего делать, показывая данные внутри бэкэнд, все метаданные элементов заказа отображаются автоматически.
Ответ 2
Я, к сожалению, не смог получить данные элемента данных по умолчанию. Я чувствую, что это может быть неправильно реализовано или даже может быть устаревшим, поскольку отсутствует поддержка и документация.
Вместо этого я использовал переменную сеанса тележки, чтобы выполнить одно и то же. Это просто массив, где каждый ключ - cart_item_key
. Значение каждого массива - это еще один массив, содержащий пару значений ключа-значения настраиваемых полей. Таким образом, это по сути то же самое, что и данные встроенной корзины, за исключением того, что они хранятся в качестве данных сеанса телеграммы.
Вот вам Gist, содержащий некоторые служебные функции:
Или, если вы хотите построить его самостоятельно, волшебство находится в 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