Search code examples
phpwordpresswoocommercehook-woocommercewoocommerce-blocks

WooCommerce Custom Cart Item Data is rendered twice in Cart and Checkout Blocks


I have added custom cart item data to products upon adding to the cart via the following code:

$cartData = array("_weekly_booking_price" => $weeklyPrice);

WC()->cart->add_to_cart( $productId, 1, 0, $cartData );

This occurs in the woocommerce_store_api_register_update_callback function when extensionCartUpdate is called on the frontend.

What I want to happen is the custom cart item data to be displayed with the product in a human-readable format. By default, the label for the custom data renders the key for that data which is less than ideal

I have tested this with the old shortcode based checkout, which works as expected

I have tried using the following filter but this results in the custom data being rendered twice, once with the unreadable key _weekly_booking_price and the second with a human-readable label which is facilitated by the filter below.

function clean_get_item_data($item_data, $cart_item_data)
{
    if (isset($cart_item_data['variation']['_weekly_booking_price'])) {

        $item_data[] = array(
            'key' => "Weekly booking price",
            'value' => wc_clean($cart_item_data['variation']['_weekly_booking_price']),
        );
    }

    return $item_data;
}
add_filter('woocommerce_get_item_data', 'clean_get_item_data', 10, 2);

Here's what that looks like


Solution

  • There are some mistakes in your code:

    You should not use the 4th argument from WC_Cart add_to_cart() method to add custom cart item data. Instead, you should use the 5th dedicated argument like:

    $cartItemData = array("weekly_booking_price" => wc_clean($weeklyPrice));
    
    WC()->cart->add_to_cart( $productId, 1, 0, [], $cartItemData );
    

    This custom data is now added as custom cart item data.


    Then to get this data displayed on mini-cart, cart and checkout, you will use:

    add_filter('woocommerce_get_item_data', 'display_custom_cart_item_data', 10, 2);
    function display_custom_cart_item_data($item_data, $cart_item )
    {
        if ( isset($cart_item['weekly_booking_price']) ) {
            $item_data[] = array(
                'key' => esc_html__("Weekly booking price", "woocommerce"),
                'value' => $cart_item['weekly_booking_price'],
            );
        }
        return $item_data;
    }
    

    If you wish to save and display the data on order items with a readable meta key, use:

    // Save and display custom fields (custom order item metadata)
    add_action( 'woocommerce_checkout_create_order_line_item', 'save_order_item_custom_meta_data', 10, 4 );
    function save_order_item_custom_meta_data( $item, $cart_item_key, $values, $order ) {
        if( isset($values['weekly_booking_price']) ) {
            $item->update_meta_data('weekly_booking_price', $values['weekly_booking_price']); 
        }
    }
    
    // Add readable "meta key" label name replacement
    add_filter('woocommerce_order_item_display_meta_key', 'filter_wc_order_item_display_meta_key', 10, 3 );
    function filter_wc_order_item_display_meta_key( $display_key, $meta, $item ) {
        if( $item->get_type() === 'line_item' ) {
            if( $meta->key === 'weekly_booking_price' ) {
                $display_key = esc_html__("Weekly booking price", "woocommerce");
            }
        }
        return $display_key;
    }
    

    Code goes in function.php file of your child theme (or in a plugin). It should work.