I am trying to order the cart contents by date, the last one added or modified must be displayed first. I tried reversing the order of the cart but its not working as expected. This is the code I tried:
//reorder cart
add_action('woocommerce_cart_loaded_from_session', 'wh_cartOrderItemsbyNewest');
function wh_cartOrderItemsbyNewest() {
//if the cart is empty do nothing
if (WC()->cart->get_cart_contents_count() == 0) {
return;
}
//array to collect cart items
$cart_sort = [];
//add cart item inside the array
foreach (WC()->cart->get_cart() as $cart_item_key => $cart_item) { print_r(WC()->cart->cart_contents[$cart_item_key][0]);
$cart_sort[$cart_item_key] = WC()->cart->cart_contents[$cart_item_key];
}
//replace the cart contents with in the reverse order
WC()->cart->cart_contents = array_reverse($cart_sort);
}
Cart items are already shown in cart by date added.
Then the last one added to the cart will be the first in the list.
The problem arises when you change the quantity of a product in the cart. In this case he would remain in his same position.
I thought of using a custom cart item data with the date of addition/modification but in this case it would create more lines of the same product.
I solved it with the Options API.
I thought about creating/updating a realtime date option when:
woocommerce_add_to_cart
the product is added to the cartwoocommerce_cart_item_removed
the product is removed from the cartwoocommerce_after_cart_item_quantity_update
the cart item quantity is updated (increased or decreased)While the option is deleted when:
woocommerce_cart_emptied
the cart is emptiedThe sort will also be applied to the mini cart.
The following function will create custom ordering of cart items based on the last_update_cart_item
option:
// sorts cart items by modification date
add_action( 'woocommerce_cart_loaded_from_session', 'sorts_cart_items_by_modification_date' );
function sorts_cart_items_by_modification_date() {
// only if the cart is not empty
if ( WC()->cart->get_cart_contents_count() == 0 ) {
return;
}
// only if the "last_update_cart_item" option exists
if ( ! $last_update = get_option( 'last_update_cart_item' ) ) {
return;
}
$cart_sort = array();
$cart_item_content = array();
foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
// gets the update date of the cart item
$cart_sort[$cart_item_key] = $last_update[$cart_item_key];
// gets the contents of the cart item
$cart_item_content[$cart_item_key] = WC()->cart->cart_contents[$cart_item_key];
}
// sorts the cart items by descending date (the last modified will be the first)
array_multisort( $cart_sort, SORT_DESC, WC()->cart->get_cart() );
// creates the new sorting with the contents of the cart items
foreach ( $cart_sort as $key => $value ) {
$sorted[$key] = $cart_item_content[$key];
}
// update cart contents with custom sorting
WC()->cart->cart_contents = $sorted;
}
While the following functions will update the last_update_cart_item
option when the product is added, changed or removed from the cart:
// update the "last_update_cart_item" option with the date the product was added to the cart
add_action( 'woocommerce_add_to_cart', 'after_woocommerce_add_to_cart', 10, 6 );
function after_woocommerce_add_to_cart( $cart_item_key, $product_id, $quantity, $variation_id, $variation, $cart_item_data ) {
$last_update = array();
if ( get_option( 'last_update_cart_item' ) ) {
$last_update = get_option( 'last_update_cart_item' );
}
// set the updated date of the cart item
$last_update[$cart_item_key] = date("Y-m-d H:i:s");
update_option( 'last_update_cart_item', $last_update );
return $cart_item_data;
}
// when the cart item is removed, it also removes the cart item key from the "last_update_cart_item" option
add_action( 'woocommerce_cart_item_removed', 'after_woocommerce_cart_item_removed', 10, 2 );
function after_woocommerce_cart_item_removed( $cart_item_key, $cart ) {
if ( $last_update = get_option( 'last_update_cart_item' ) ) {
if ( array_key_exists( $cart_item_key, $last_update ) ) {
// removes the cart item key from the "last_update_cart_item" option
unset( $last_update[$cart_item_key] );
update_option( 'last_update_cart_item', $last_update );
}
}
}
// when the quantity of the cart item updates, sets or updates the date
add_action( 'woocommerce_after_cart_item_quantity_update', 'update_cart_item_data_after_cart_item_quantity_update', 10, 4 );
function update_cart_item_data_after_cart_item_quantity_update( $cart_item_key, $quantity, $old_quantity, $cart ) {
$last_update = array();
if ( get_option( 'last_update_cart_item' ) ) {
$last_update = get_option( 'last_update_cart_item' );
}
// updates the date of the cart item whose quantity has been changed
$last_update[$cart_item_key] = date("Y-m-d H:i:s");
update_option( 'last_update_cart_item', $last_update );
}
// when the cart is empty delete the "last_update_cart_item" option
add_action( 'woocommerce_cart_emptied', 'after_woocommerce_cart_emptied', 10, 1 );
function after_woocommerce_cart_emptied( $cart ) {
// delete the "last_update_cart_item" option
delete_option( 'last_update_cart_item' );
}
The code has been tested and works. Add it to your active theme's functions.php.