Подтвердить что ты не робот

Как получить 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 );
4b9b3361

Ответ 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, содержащий некоторые служебные функции:

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