web-dev-qa-db-fra.com

Comment récupérer cart_item_data avec WooCommerce?

Pendant la fonction add_to_cart , il y a un filtre pour ajouter des "données d'article de panier". Le filtre est woocommerce_add_cart_item_data. Je m'attendais à y stocker mes données de plug-in personnalisé, afin que les données soient stockées par rapport à l'article et que plusieurs produits puissent être ajoutés avec des données différentes.

Tout cela semblait fonctionner, mais je ne suis pas en mesure de récupérer les données. Je ne peux pas comprendre. Les données sont là , je peux les voir dans une chaîne sérialisée, mais je ne peux pas les extraire.

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>';

Le premier vidage de WC() a une propriété: session->_data->cart->(serialized data). La propriété _data est protégée, mais je peux voir mon champ personnalisé à l'intérieur des données sérialisées.

Le $ cart_item est un tableau avec product_id Et quelques autres données, mais il n'inclut pas mes données personnalisées :(

Enfin, en utilisant la méthode get_item_data() , je pensais avoir tout compris. J'ai passé l'objet du panier et ... une chaîne vide. Même si je passe la clé, plutôt que l'article du panier lui-même.

Comment suis-je censé accéder aux données de l'article du panier?


Voici la fonction "Ajouter les données des articles du panier", qui fonctionne (ou du moins semble fonctionner):

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 );
17
Radley Sustaire

J'étais dans la même situation aujourd'hui et suis tombé sur cette question après quelques recherches. Après une ingénierie inverse, j'ai trouvé le problème et je veux fournir une solution pour d'autres qui peuvent également trébucher sur cette question.

Le problème est que les données sont nettoyées lorsque les éléments du panier sont restaurés à partir de la session. Ainsi, les données supplémentaires de l'article du panier IS stockées dans la session mais à la demande suivante, elles ne sont pas restaurées.

Il existe un filtre "woocommerce_get_cart_item_from_session". En tant que premier paramètre, vous obtenez l'article du panier aseptisé (sans données supplémentaires) et en tant que deuxième toutes les données qui ont été stockées dans la session (y compris les données supplémentaires).

La solution consiste à s'y connecter et à restaurer également les données de votre article de panier personnalisé.

Exemple de code:

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 );

Pour afficher également les données sur la page panier/caisse, vous pouvez utiliser le code suivant:

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 );

La dernière chose est maintenant de sauvegarder les données lors de la commande:

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 );

Vous n'avez rien d'autre à faire que d'afficher les données à l'intérieur du backend, toutes les métadonnées de l'article de commande s'affichent automatiquement.

41
Stefan

Malheureusement, je n'ai pas pu faire fonctionner les données par défaut des articles du panier. Je pense qu'il peut ne pas être correctement mis en œuvre, ou peut même être déconseillé, car il manque de support et de documentation.

Au lieu de cela, j'ai utilisé une variable de session de panier pour accomplir la même chose. C'est simplement un tableau où chaque clé est le cart_item_key. La valeur de chaque tableau est encore un autre tableau, contenant une paire clé-valeur de champs personnalisés. C'est donc essentiellement la même chose que les données d'élément de panier intégrées, sauf qu'elles sont stockées à la place en tant que données de session de panier.

Voici un Gist contenant quelques fonctions utilitaires pour vous faciliter la tâche:

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


Ou si vous voulez le construire vous-même, la magie est dans WC()->session. Voici les deux fonctions clés pour que cela fonctionne:

WC()->session->get('_my_cart_item_data');
WC()->session->set('_my_cart_item_data', $cart_item_data_array);

Voici les crochets d'action dont vous aurez besoin:

<<<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
4
Radley Sustaire