Как получить данные о товарах в корзине с помощью 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 );
2 answers
Сегодня я был в такой же ситуации и наткнулся на этот вопрос после некоторых исследований. После некоторого обратного проектирования я обнаружил проблему и хочу предложить решение для других, которые также могут столкнуться с этим вопросом.
Проблема в том, что данные очищаются, когда элементы корзины восстанавливаются из сеанса. Таким образом, дополнительные данные о товарах корзины сохраняются в сеансе, но при следующем запросе они не восстанавливаются.
Есть фильтр "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 );
Вам не нужно делать ничего другого, чтобы отобразить данные внутри серверной части, все метаданные элемента заказа отображаются автоматически.
К сожалению, я не смог заставить данные о товарах в корзине по умолчанию работать. Я чувствую, что это может быть реализовано неправильно или даже устарело, так как отсутствует поддержка и документация.
Вместо этого я использовал переменную сеанса cart для выполнения того же самого. Это просто массив, где каждый ключ является cart_item_key
. Значение каждого массива является еще одним массивом, содержащим пару пользовательских полей "ключ-значение". Таким образом, это по сути то же самое, что и встроенные данные о товарах в корзине, за исключением вместо этого они хранятся в виде данных сеанса корзины.
Вот суть, содержащая некоторые полезные функции для упрощения:
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