I need to sort my cart items by variation addon values.
For example I have 5 items in cart, and they have variation date:
first item date - 2016-05-05;
second 2016-05-08;
third 2016-05-20 and so on.
How can I sort them in cart ? I found that all info are in $cart_item[‘addons’] , but don’t find solution for how to sort them.
I editing my cart.php
<?php
foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
$_product = apply_filters( 'woocommerce_cart_item_product', $cart_item['data'], $cart_item, $cart_item_key );
$product_id = apply_filters( 'woocommerce_cart_item_product_id', $cart_item['product_id'], $cart_item, $cart_item_key );
if ( $_product && $_product->exists() && $cart_item['quantity'] > 0 && apply_filters( 'woocommerce_cart_item_visible', true, $cart_item, $cart_item_key ) ) {
?>
<tr class="<?php echo esc_attr( apply_filters( 'woocommerce_cart_item_class', 'cart_item', $cart_item, $cart_item_key ) ); ?>">
<td class="product-name">
<div class="product-thumbnail">
<?php
$thumbnail = apply_filters( 'woocommerce_cart_item_thumbnail', $_product->get_image(), $cart_item, $cart_item_key );
if ( ! $_product->is_visible() )
echo $thumbnail;
else
printf( '%s', $_product->get_permalink(), $thumbnail );
?>
</div>
</td>
<td class="product-details">
<div class="cart-item-details">
<?php
if ( ! $_product->is_visible() )
echo apply_filters( 'woocommerce_cart_item_name', $_product->get_title(), $cart_item, $cart_item_key );
else
echo apply_filters( 'woocommerce_cart_item_name', sprintf( '%s', $_product->get_permalink(), $_product->get_title() ), $cart_item, $cart_item_key );
// Meta data
echo WC()->cart->get_item_data( $cart_item );
// Backorder notification
if ( $_product->backorders_require_notification() && $_product->is_on_backorder( $cart_item['quantity'] ) )
echo '<p class="backorder_notification">' . esc_html__( 'Available on backorder', 'xstore' ) . '</p>';
?>
<span class="mobile-price">
<?php
echo apply_filters( 'woocommerce_cart_item_price', WC()->cart->get_product_price( $_product ), $cart_item, $cart_item_key );
?>
</span>
</div>
</td>
<td class="product-price">
<?php
echo apply_filters( 'woocommerce_cart_item_price', WC()->cart->get_product_price( $_product ), $cart_item, $cart_item_key );
?>
</td>
<td class="product-quantity">
<?php
if ( $_product->is_sold_individually() ) {
$product_quantity = sprintf( '1 <input type="hidden" name="cart[%s][qty]" value="1" />', $cart_item_key );
} else {
$product_quantity = woocommerce_quantity_input( array(
'input_name' => "cart[{$cart_item_key}][qty]",
'input_value' => $cart_item['quantity'],
'max_value' => $_product->backorders_allowed() ? '' : $_product->get_stock_quantity(),
'min_value' => '0'
), $_product, false );
}
echo apply_filters( 'woocommerce_cart_item_quantity', $product_quantity, $cart_item_key );
?>
</td>
<td class="product-subtotal">
<?php
echo apply_filters( 'woocommerce_cart_item_subtotal', WC()->cart->get_product_subtotal( $_product, $cart_item['quantity'] ), $cart_item, $cart_item_key );
?>
</td>
<td class="product-remove">
<?php
echo apply_filters( 'woocommerce_cart_item_remove_link', sprintf( 'X', esc_url( WC()->cart->get_remove_url( $cart_item_key ) ), __( 'Pašalinti produktą', 'xstore' ) ), $cart_item_key );
?>
</td>
</tr>
<?php
}
}
Related
I've been trying to figure out how can I make the value on the product meta data shown on the cart to be editable and saved when clicking the update quote button. When I try to update the value on the BOP field for each product, it does not reflect properly
I've made some work in progress but can never seem to make it work
cart.php
<?php
foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
$_product = apply_filters( 'woocommerce_cart_item_product', $cart_item['data'], $cart_item, $cart_item_key );
$product_id = apply_filters( 'woocommerce_cart_item_product_id', $cart_item['product_id'], $cart_item, $cart_item_key );
if ( $_product && $_product->exists() && $cart_item['quantity'] > 0 && apply_filters( 'woocommerce_cart_item_visible', true, $cart_item, $cart_item_key ) ) {
$product_permalink = apply_filters( 'woocommerce_cart_item_permalink', $_product->is_visible() ? $_product->get_permalink( $cart_item ) : '', $cart_item, $cart_item_key );
?>
<tr class="woocommerce-cart-form__cart-item <?php echo esc_attr( apply_filters( 'woocommerce_cart_item_class', 'cart_item', $cart_item, $cart_item_key ) ); ?>">
<td class="product-remove">
<?php
echo apply_filters( // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
'woocommerce_cart_item_remove_link',
sprintf(
'×',
esc_url( wc_get_cart_remove_url( $cart_item_key ) ),
esc_html__( 'Remove this item', 'woocommerce' ),
esc_attr( $product_id ),
esc_attr( $_product->get_sku() )
),
$cart_item_key
);
?>
</td>
<td class="product-thumbnail">
<?php
$thumbnail = apply_filters( 'woocommerce_cart_item_thumbnail', $_product->get_image(), $cart_item, $cart_item_key );
if ( ! $product_permalink ) {
echo $thumbnail; // PHPCS: XSS ok.
} else {
printf( '%s', esc_url( $product_permalink ), $thumbnail ); // PHPCS: XSS ok.
}
?>
</td>
<td class="product-name" data-title="<?php esc_attr_e( 'Product', 'woocommerce' ); ?>">
<?php
if ( ! $product_permalink ) {
echo wp_kses_post( apply_filters( 'woocommerce_cart_item_name', $_product->get_name(), $cart_item, $cart_item_key ) . ' ' );
} else {
echo wp_kses_post( apply_filters( 'woocommerce_cart_item_name', sprintf( '%s', esc_url( $product_permalink ), $_product->get_name() ), $cart_item, $cart_item_key ) );
}
do_action( 'woocommerce_after_cart_item_name', $cart_item, $cart_item_key );
?>
<?php
// Meta data.
// echo wc_get_formatted_cart_item_data( $cart_item ); // PHPCS: XSS ok. ?>
<div class="box-type-field">
<span>BOP: <input class="box-type" cart_item_key="<?php echo $cart_item['key'] ?>" type="number" value="<?php echo $cart_item['BOP'] ?>" /></span>
</div>
<?php
// Backorder notification.
if ( $_product->backorders_require_notification() && $_product->is_on_backorder( $cart_item['quantity'] ) ) {
echo wp_kses_post( apply_filters( 'woocommerce_cart_item_backorder_notification', '<p class="backorder_notification">' . esc_html__( 'Available on backorder', 'woocommerce' ) . '</p>', $product_id ) );
}
?>
</td>
<td class="product-quantity" data-title="<?php esc_attr_e( 'Quantity', 'woocommerce' ); ?>">
<?php
if ( $_product->is_sold_individually() ) {
$product_quantity = sprintf( '1 <input type="hidden" name="cart[%s][qty]" value="1" />', $cart_item_key );
} else {
$product_quantity = woocommerce_quantity_input(
array(
'input_name' => "cart[{$cart_item_key}][qty]",
'input_value' => $cart_item['quantity'],
'max_value' => $_product->get_max_purchase_quantity(),
'min_value' => '0',
'product_name' => $_product->get_name(),
),
$_product,
false
);
}
echo apply_filters( 'woocommerce_cart_item_quantity', $product_quantity, $cart_item_key, $cart_item ); // PHPCS: XSS ok.
?>
</td>
</tr>
<?php
}
}
?>
JS
jQuery('.box-type-field .box-type').on('change', function () {
var cartItemKey = jQuery(this).attr("cart_item_key");
var boxType = jQuery(this).val();
jQuery.ajax({
type : "post",
url : '/wp-admin/admin-ajax.php',
datatype: 'json',
data : {
action : "update_cart_boxtype",
cart_item_key : cartItemKey,
box_type : boxType,
},
success: function(cartItem) {
cartItemKey = cartItem[0];
cartItemQty = cartItem[1];
if (cartItem) jQuery('input[name="cart['+cartItemKey+'][qty]"]').val(cartItemQty); // update quantity
jQuery('.woocommerce-cart-form button[type="submit"]').click(); // submit form
}
})
})
PHP (functions.php)
function update_cart_boxtype_init() {
if ( ! WC()->cart->is_empty() ) {
$cart_item_key = (isset($_POST['cart_item_key']))?$_POST['cart_item_key'] : '';
$cart_item = WC()->cart->cart_contents[ $cart_item_key ];
$box_type = (isset($_POST['box_type']))?$_POST['box_type'] : '';
$cart_updated = false;
$cart_item_key_new = WC()->cart->generate_cart_id( $cart_item['product_id'], $cart_item['variation_id'], $cart_item['variation'], ['box-type'=>$box_type] );
$found = WC()->cart->find_product_in_cart( $cart_item_key_new );
if ($found != '') {
$new_qty = $cart_item['quantity'] + WC()->cart->cart_contents[ $cart_item_key_new ]['quantity'];
WC()->cart->remove_cart_item($cart_item_key);
wp_send_json_success([$cart_item_key_new, $new_qty]);
} else {
WC()->cart->add_to_cart($cart_item['product_id'], $cart_item['quantity'], $cart_item['variation_id'], $cart_item['variation'], ['box-type' => $box_type]);
$cart_updated = true;
WC()->cart->remove_cart_item($cart_item_key);
wp_send_json_success(false);
}
}
wp_die();
}
add_action( 'wp_ajax_update_cart_boxtype', 'update_cart_boxtype_init' );
add_action( 'wp_ajax_nopriv_update_cart_boxtype', 'update_cart_boxtype_init' );
Some errors indicated:
1.) When I try to update the value it returns 404 on the console as shown below
Looking at your ajax function I will say that when you define this wp_send_json_success(false); your javascript is expecting an array of something and you are submitting a boolean.
if you are getting a 404 error then it seems like your ajax url is wrong:
you can define it on the page as a localize_script to an enqueued script
$args = array(
'ajaxurl' => admin_url( 'admin-ajax.php' )
);
wp_localize_script( 'YOUR_ENQUEUED_SCRIPT', 'ajax', $args );
and call it in your js:
ajax.ajaxurl
or defined in the theme:
<?php $ajax_url = admin_url( 'admin-ajax.php' ); ?>
<?php echo $ajax_url; ?>
in the woocommerce mini-cart I'd like to display an input to adjust the quantity of each product.
I added line in the mini-cart.php file of my Storefront child theme (using the function woocommerce_quantity_input), it displays the input, but the cart is not 'updated'.
Any idea how to do this?
See the last line of:
foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
$_product = apply_filters( 'woocommerce_cart_item_product', $cart_item['data'], $cart_item, $cart_item_key );
$product_id = apply_filters( 'woocommerce_cart_item_product_id', $cart_item['product_id'], $cart_item, $cart_item_key );
if ( $_product && $_product->exists() && $cart_item['quantity'] > 0 && apply_filters( 'woocommerce_widget_cart_item_visible', true, $cart_item, $cart_item_key ) ) {
$product_name = apply_filters( 'woocommerce_cart_item_name', $_product->get_name(), $cart_item, $cart_item_key );
$thumbnail = apply_filters( 'woocommerce_cart_item_thumbnail', $_product->get_image(), $cart_item, $cart_item_key );
$product_price = apply_filters( 'woocommerce_cart_item_price', WC()->cart->get_product_price( $_product ), $cart_item, $cart_item_key );
$product_permalink = apply_filters( 'woocommerce_cart_item_permalink', $_product->is_visible() ? $_product->get_permalink( $cart_item ) : '', $cart_item, $cart_item_key );
?>
<li class="woocommerce-mini-cart-item <?php echo esc_attr( apply_filters( 'woocommerce_mini_cart_item_class', 'mini_cart_item', $cart_item, $cart_item_key ) ); ?>">
<?php
//split product name and color
$pattern = '/ [^a-zA-Z0-9 ]+| –/';
$matches = array();
$dummy = preg_match($pattern, $product_name, $matches);
$posi = strpos($product_name, $matches[0]);
$productnamename = substr($product_name, 0, $posi);
$dashAndProductcolor = substr($product_name, $posi);
?>
<?php if ( empty( $product_permalink ) ) : ?>
<?php echo $thumbnail; ?>
<?php echo '<span class="minicart-prod-name">'.$productnamename.'</span><br/>' ?>
<?php echo '<span class="minicart-prod-color">'.$dashAndProductcolor.'</span>' ?>
<?php else : ?>
<a href="<?php echo esc_url( $product_permalink ); ?>">
<?php echo $thumbnail; ?>
<?php echo '<span class="minicart-prod-name">'.$productnamename.'</span><br/>' ?>
<?php echo wc_get_formatted_cart_item_data( $cart_item ); ?>
<?php echo '<span class="minicart-prod-color">'.$dashAndProductcolor.'</span>' ?>
</a>
<?php echo apply_filters( 'woocommerce_widget_cart_item_quantity', '<span class="each-price">' . sprintf( '%s', $product_price ) . '</span>', $cart_item, $cart_item_key ); ?>
<?php endif; ?>
<?php echo apply_filters( 'woocommerce_widget_cart_item_quantity', '<span class="quantity">' . sprintf( '%s', $cart_item['quantity'] ) . '</span>', $cart_item, $cart_item_key ); ?>
<?php
echo woocommerce_quantity_input( array('input_value' => $cart_item['quantity']),$cart_item['data'], false );
?>
Thanks you for your help. I have a very unique requirement for woocommerce cart page. What i want is to split products based on categories. For example:
Category name 1:
product 1
product 2
product 3
Category name 2:
product 1
product 2
product 3
Assumptions: Each product is assigned a single category, so i want to pull all the categories and display products which is in that category.
I have tried using the following code but it display all the categories.
Your help will be highly appreciated.
<?php
/**
* Cart Page
*
* This template can be overridden by copying it to yourtheme/woocommerce/cart/cart.php.
*
* HOWEVER, on occasion WooCommerce will need to update template files and you
* (the theme developer) will need to copy the new files to your theme to
* maintain compatibility. We try to do this as little as possible, but it does
* happen. When this occurs the version of the template file will be bumped and
* the readme will list any important changes.
*
* #see https://docs.woocommerce.com/document/template-structure/
* #package WooCommerce/Templates
* #version 3.7.0
*/
defined( 'ABSPATH' ) || exit;
do_action( 'woocommerce_before_cart' ); ?>
<style>
table {
position: relative;
}
form.woocommerce-cart-form {
font-size: 0;
}
td.aa {
width: 100% !important;
position: absolute;
border: 0 !IMPORTANT;
padding: 4px !IMPORTANT;
font-size: 23px !important;
background: #28d18b;
color: #fff;
text-align: center;
display: none !Important;
}
</style>
<form class="woocommerce-cart-form" action="<?php echo esc_url( wc_get_cart_url() ); ?>" method="post">
<?php do_action( 'woocommerce_before_cart_table' ); ?>
<table class="shop_table shop_table_responsive cart woocommerce-cart-form__contents" cellspacing="0">
<thead>
<tr>
<th class="product-remove"> </th>
<th class="product-thumbnail"> </th>
<th class="product-name"><?php esc_html_e( 'Product', 'woocommerce' ); ?></th>
<th class="product-price"><?php esc_html_e( 'Price', 'woocommerce' ); ?></th>
<th class="product-quantity"><?php esc_html_e( 'Quantity', 'woocommerce' ); ?></th>
<th class="product-subtotal"><?php esc_html_e( 'Total', 'woocommerce' ); ?></th>
</tr>
</thead>
<tbody>
<?php do_action( 'woocommerce_before_cart_contents' ); ?>
<?php
$args = array(
'taxonomy' => 'product_cat',
'orderby' => 'name',
'show_count' => '0',
'pad_counts' => '0',
'hide_empty' => '0'
);
$cats = get_categories( $args );
foreach ($cats as $cat) {
$category_id = $cat->term_id;
echo "<tr>";
echo "<td class='aa'>";
foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
if ( has_term( $category_id, 'product_cat', $cart_item['product_id'] ) ) {
echo $cat->name ;
$_product = apply_filters( 'woocommerce_cart_item_product', $cart_item['data'], $cart_item, $cart_item_key );
$product_id = apply_filters( 'woocommerce_cart_item_product_id', $cart_item['product_id'], $cart_item, $cart_item_key );
if ( $_product && $_product->exists() && $cart_item['quantity'] > 0 && apply_filters( 'woocommerce_cart_item_visible', true, $cart_item, $cart_item_key ) ) {
$product_permalink = apply_filters( 'woocommerce_cart_item_permalink', $_product->is_visible() ? $_product->get_permalink( $cart_item ) : '', $cart_item, $cart_item_key );
?>
<tr class="woocommerce-cart-form__cart-item <?php echo esc_attr( apply_filters( 'woocommerce_cart_item_class', 'cart_item', $cart_item, $cart_item_key ) ); ?>">
<td class="product-remove">
<?php
echo apply_filters( // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
'woocommerce_cart_item_remove_link',
sprintf(
'×',
esc_url( wc_get_cart_remove_url( $cart_item_key ) ),
esc_html__( 'Remove this item', 'woocommerce' ),
esc_attr( $product_id ),
esc_attr( $_product->get_sku() )
),
$cart_item_key
);
?>
</td>
<td class="product-thumbnail">
<?php
$thumbnail = apply_filters( 'woocommerce_cart_item_thumbnail', $_product->get_image(), $cart_item, $cart_item_key );
if ( ! $product_permalink ) {
echo $thumbnail; // PHPCS: XSS ok.
} else {
printf( '%s', esc_url( $product_permalink ), $thumbnail ); // PHPCS: XSS ok.
}
?>
</td>
<td class="product-name" data-title="<?php esc_attr_e( 'Product', 'woocommerce' ); ?>">
<?php
if ( ! $product_permalink ) {
echo wp_kses_post( apply_filters( 'woocommerce_cart_item_name', $_product->get_name(), $cart_item, $cart_item_key ) . ' ' );
} else {
echo wp_kses_post( apply_filters( 'woocommerce_cart_item_name', sprintf( '%s', esc_url( $product_permalink ), $_product->get_name() ), $cart_item, $cart_item_key ) );
}
do_action( 'woocommerce_after_cart_item_name', $cart_item, $cart_item_key );
// Meta data.
echo wc_get_formatted_cart_item_data( $cart_item ); // PHPCS: XSS ok.
// Backorder notification.
if ( $_product->backorders_require_notification() && $_product->is_on_backorder( $cart_item['quantity'] ) ) {
echo wp_kses_post( apply_filters( 'woocommerce_cart_item_backorder_notification', '<p class="backorder_notification">' . esc_html__( 'Available on backorder', 'woocommerce' ) . '</p>', $product_id ) );
}
?>
</td>
<td class="product-price" data-title="<?php esc_attr_e( 'Price', 'woocommerce' ); ?>">
<?php
echo apply_filters( 'woocommerce_cart_item_price', WC()->cart->get_product_price( $_product ), $cart_item, $cart_item_key ); // PHPCS: XSS ok.
?>
</td>
<td class="product-quantity" data-title="<?php esc_attr_e( 'Quantity', 'woocommerce' ); ?>">
<?php
if ( $_product->is_sold_individually() ) {
$product_quantity = sprintf( '1 <input type="hidden" name="cart[%s][qty]" value="1" />', $cart_item_key );
} else {
$product_quantity = woocommerce_quantity_input(
array(
'input_name' => "cart[{$cart_item_key}][qty]",
'input_value' => $cart_item['quantity'],
'max_value' => $_product->get_max_purchase_quantity(),
'min_value' => '0',
'product_name' => $_product->get_name(),
),
$_product,
false
);
}
echo apply_filters( 'woocommerce_cart_item_quantity', $product_quantity, $cart_item_key, $cart_item ); // PHPCS: XSS ok.
?>
</td>
<td class="product-subtotal" data-title="<?php esc_attr_e( 'Total', 'woocommerce' ); ?>">
<?php
echo apply_filters( 'woocommerce_cart_item_subtotal', WC()->cart->get_product_subtotal( $_product, $cart_item['quantity'] ), $cart_item, $cart_item_key ); // PHPCS: XSS ok.
?>
</td>
</tr>
<?php
}
}
}
echo "</td>";
echo "</tr>";
}
?>
</tbody>
</table>
<table class="shop_table shop_table_responsive cart woocommerce-cart-form__contents" cellspacing="0">
<tbody>
<?php do_action( 'woocommerce_cart_contents' ); ?>
<tr>
<td colspan="6" class="actions">
<?php if ( wc_coupons_enabled() ) { ?>
<div class="coupon">
<label for="coupon_code"><?php esc_html_e( 'Coupon:', 'woocommerce' ); ?></label> <input type="text" name="coupon_code" class="input-text" id="coupon_code" value="" placeholder="<?php esc_attr_e( 'Coupon code', 'woocommerce' ); ?>" /> <button type="submit" class="button" name="apply_coupon" value="<?php esc_attr_e( 'Apply coupon', 'woocommerce' ); ?>"><?php esc_attr_e( 'Apply coupon', 'woocommerce' ); ?></button>
<?php do_action( 'woocommerce_cart_coupon' ); ?>
</div>
<?php } ?>
<button type="submit" class="button" name="update_cart" value="<?php esc_attr_e( 'Update cart', 'woocommerce' ); ?>"><?php esc_html_e( 'Update cart', 'woocommerce' ); ?></button>
<?php do_action( 'woocommerce_cart_actions' ); ?>
<?php wp_nonce_field( 'woocommerce-cart', 'woocommerce-cart-nonce' ); ?>
</td>
</tr>
<?php do_action( 'woocommerce_after_cart_contents' ); ?>
</tbody>
</table>
<?php do_action( 'woocommerce_after_cart_table' ); ?>
</form>
<?php do_action( 'woocommerce_before_cart_collaterals' ); ?>
<div class="cart-collaterals">
<?php
/**
* Cart collaterals hook.
*
* #hooked woocommerce_cross_sell_display
* #hooked woocommerce_cart_totals - 10
*/
do_action( 'woocommerce_cart_collaterals' );
?>
</div>
<?php do_action( 'woocommerce_after_cart' ); ?>
Override cart.php template first, after then just replace table <tbody></tbody> section with follows -
<tbody>
<?php do_action( 'woocommerce_before_cart_contents' ); ?>
<?php
$cat_wisw_pros = array();
foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
$product_id = $cart_item['product_id'];
$cat_ids = wp_get_post_terms( $product_id, 'product_cat', array( 'fields' => 'ids' ) );
foreach ( $cat_ids as $id ) {
$cat_wisw_pros[$id][$cart_item_key] = $cart_item;
}
}
ksort( $cat_wisw_pros ); // Cat ID wise sort
$grouped_cart_items = array();
foreach ( $cat_wisw_pros as $cat_id => $cart_items ) {
$term = get_term( $cat_id, 'product_cat' );
?>
<tr>
<td colspan="6" class=""><strong><?php echo $term->name; ?></strong></td>
</tr>
<?php
foreach ( $cart_items as $cart_item_key => $cart_item ) {
if( !array_key_exists( $cart_item_key, $grouped_cart_items ) ) {
$_product = apply_filters( 'woocommerce_cart_item_product', $cart_item['data'], $cart_item, $cart_item_key );
$product_id = apply_filters( 'woocommerce_cart_item_product_id', $cart_item['product_id'], $cart_item, $cart_item_key );
if ( $_product && $_product->exists() && $cart_item['quantity'] > 0 && apply_filters( 'woocommerce_cart_item_visible', true, $cart_item, $cart_item_key ) ) {
$product_permalink = apply_filters( 'woocommerce_cart_item_permalink', $_product->is_visible() ? $_product->get_permalink( $cart_item ) : '', $cart_item, $cart_item_key );
?>
<tr class="woocommerce-cart-form__cart-item <?php echo esc_attr( apply_filters( 'woocommerce_cart_item_class', 'cart_item', $cart_item, $cart_item_key ) ); ?>">
<td class="product-remove">
<?php
echo apply_filters( // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
'woocommerce_cart_item_remove_link',
sprintf(
'×',
esc_url( wc_get_cart_remove_url( $cart_item_key ) ),
esc_html__( 'Remove this item', 'woocommerce' ),
esc_attr( $product_id ),
esc_attr( $_product->get_sku() )
),
$cart_item_key
);
?>
</td>
<td class="product-thumbnail">
<?php
$thumbnail = apply_filters( 'woocommerce_cart_item_thumbnail', $_product->get_image(), $cart_item, $cart_item_key );
if ( ! $product_permalink ) {
echo $thumbnail; // PHPCS: XSS ok.
} else {
printf( '%s', esc_url( $product_permalink ), $thumbnail ); // PHPCS: XSS ok.
}
?>
</td>
<td class="product-name" data-title="<?php esc_attr_e( 'Product', 'woocommerce' ); ?>">
<?php
if ( ! $product_permalink ) {
echo wp_kses_post( apply_filters( 'woocommerce_cart_item_name', $_product->get_name(), $cart_item, $cart_item_key ) . ' ' );
} else {
echo wp_kses_post( apply_filters( 'woocommerce_cart_item_name', sprintf( '%s', esc_url( $product_permalink ), $_product->get_name() ), $cart_item, $cart_item_key ) );
}
do_action( 'woocommerce_after_cart_item_name', $cart_item, $cart_item_key );
// Meta data.
echo wc_get_formatted_cart_item_data( $cart_item ); // PHPCS: XSS ok.
// Backorder notification.
if ( $_product->backorders_require_notification() && $_product->is_on_backorder( $cart_item['quantity'] ) ) {
echo wp_kses_post( apply_filters( 'woocommerce_cart_item_backorder_notification', '<p class="backorder_notification">' . esc_html__( 'Available on backorder', 'woocommerce' ) . '</p>', $product_id ) );
}
?>
</td>
<td class="product-price" data-title="<?php esc_attr_e( 'Price', 'woocommerce' ); ?>">
<?php
echo apply_filters( 'woocommerce_cart_item_price', WC()->cart->get_product_price( $_product ), $cart_item, $cart_item_key ); // PHPCS: XSS ok.
?>
</td>
<td class="product-quantity" data-title="<?php esc_attr_e( 'Quantity', 'woocommerce' ); ?>">
<?php
if ( $_product->is_sold_individually() ) {
$product_quantity = sprintf( '1 <input type="hidden" name="cart[%s][qty]" value="1" />', $cart_item_key );
} else {
$product_quantity = woocommerce_quantity_input(
array(
'input_name' => "cart[{$cart_item_key}][qty]",
'input_value' => $cart_item['quantity'],
'max_value' => $_product->get_max_purchase_quantity(),
'min_value' => '0',
'product_name' => $_product->get_name(),
),
$_product,
false
);
}
echo apply_filters( 'woocommerce_cart_item_quantity', $product_quantity, $cart_item_key, $cart_item ); // PHPCS: XSS ok.
?>
</td>
<td class="product-subtotal" data-title="<?php esc_attr_e( 'Total', 'woocommerce' ); ?>">
<?php
echo apply_filters( 'woocommerce_cart_item_subtotal', WC()->cart->get_product_subtotal( $_product, $cart_item['quantity'] ), $cart_item, $cart_item_key ); // PHPCS: XSS ok.
?>
</td>
</tr>
<?php
}
}
}
}
?>
<?php do_action( 'woocommerce_cart_contents' ); ?>
<tr>
<td colspan="6" class="actions">
<?php if ( wc_coupons_enabled() ) { ?>
<div class="coupon">
<label for="coupon_code"><?php esc_html_e( 'Coupon:', 'woocommerce' ); ?></label> <input type="text" name="coupon_code" class="input-text" id="coupon_code" value="" placeholder="<?php esc_attr_e( 'Coupon code', 'woocommerce' ); ?>" /> <button type="submit" class="button" name="apply_coupon" value="<?php esc_attr_e( 'Apply coupon', 'woocommerce' ); ?>"><?php esc_attr_e( 'Apply coupon', 'woocommerce' ); ?></button>
<?php do_action( 'woocommerce_cart_coupon' ); ?>
</div>
<?php } ?>
<button type="submit" class="button" name="update_cart" value="<?php esc_attr_e( 'Update cart', 'woocommerce' ); ?>"><?php esc_html_e( 'Update cart', 'woocommerce' ); ?></button>
<?php do_action( 'woocommerce_cart_actions' ); ?>
<?php wp_nonce_field( 'woocommerce-cart', 'woocommerce-cart-nonce' ); ?>
</td>
</tr>
<?php do_action( 'woocommerce_after_cart_contents' ); ?>
</tbody>
I'm trying to make my custom mini-cart. Cart should be updated without page reload(ajax) after item removing, but it is not happens, I have infinite load on front-end and see changes only after page reload.
My mini-cart action
function my_wc_mini_cart() {
if ( in_array( 'woocommerce/woocommerce.php', apply_filters( 'active_plugins', get_option( 'active_plugins' ) ) ) ) {
$count = WC()->cart->cart_contents_count;
$cart = WC()->cart->get_cart();
?>
<?php _e('Cart', 'frosted'); ?> <span class="cart__amount"><?php echo esc_html( $count ); ?></span>
<div class="sub-menu sub-menu--right sub-menu--cart">
<?php
foreach ( $cart as $cart_item_key => $cart_item ):
$_product = apply_filters( 'woocommerce_cart_item_product', $cart_item['data'], $cart_item, $cart_item_key );
$product_id = apply_filters( 'woocommerce_cart_item_product_id', $cart_item['product_id'], $cart_item, $cart_item_key );
if ( $_product && $_product->exists() && $cart_item['quantity'] > 0 && apply_filters( 'woocommerce_widget_cart_item_visible', true, $cart_item, $cart_item_key ) ) {
$product_name = apply_filters( 'woocommerce_cart_item_name', $_product->get_name(), $cart_item, $cart_item_key );
$thumbnail = apply_filters( 'woocommerce_cart_item_thumbnail', $_product->get_image(), $cart_item, $cart_item_key );
$product_price = apply_filters( 'woocommerce_cart_item_price', WC()->cart->get_product_price( $_product ), $cart_item, $cart_item_key );
$variation_val = $cart_item['variation']['attribute_pa_size'];
$term_obj = get_term_by('slug', $variation_val, 'pa_size');
$size_name = $term_obj->name;
?>
<div class="media mini-cart__item woocommerce-mini-cart-item <?php echo esc_attr( apply_filters( 'woocommerce_mini_cart_item_class', 'mini_cart_item', $cart_item, $cart_item_key ) ); ?>">
<?php echo $thumbnail; ?>
<div class="media-body mini-cart__item_body">
<div class="mini-cart__item__heading mt-0"><?php echo $product_name; ?></div>
<?php
echo apply_filters( 'woocommerce_widget_cart_item_quantity', '<div class="cart__item__price">' . sprintf( '%s × %s', $cart_item['quantity'], $product_price ) . '</div>', $cart_item, $cart_item_key ); ?>
<div class="mini-cart__item__size"><?php echo $size_name; ?></div>
</div>
<div class="mini-cart__item_remove ">
<?php
echo apply_filters( 'woocommerce_cart_item_remove_link', sprintf(
'×',
esc_url( wc_get_cart_remove_url( $cart_item_key ) ),
__( 'Remove this item', 'woocommerce' ),
esc_attr( $product_id ),
esc_attr( $cart_item_key ),
esc_attr( $_product->get_sku() )
), $cart_item_key );
?>
</div>
</div>
<?php } ?>
<?php endforeach; ?>
<span class="btn__text"><?php _e('Checkout', 'frosted'); ?></span>
</div>
<?php
}
}
add_action( 'frosted_header_top', 'my_wc_mini_cart' );
Action for updating cart using ajax, maybe I'm suing wrong hook...
function my_header_add_to_cart_fragment( $fragments ) {
ob_start();
$count = WC()->cart->cart_contents_count;
$cart = WC()->cart->get_cart();
?>
<?php _e('Cart', 'frosted'); ?> <span class="cart__amount"><?php echo esc_html( $count ); ?></span>
<div class="sub-menu sub-menu--right sub-menu--cart">
<?php
foreach ( $cart as $cart_item_key => $cart_item ):
$_product = apply_filters( 'woocommerce_cart_item_product', $cart_item['data'], $cart_item, $cart_item_key );
$product_id = apply_filters( 'woocommerce_cart_item_product_id', $cart_item['product_id'], $cart_item, $cart_item_key );
if ( $_product && $_product->exists() && $cart_item['quantity'] > 0 && apply_filters( 'woocommerce_widget_cart_item_visible', true, $cart_item, $cart_item_key ) ) {
$product_name = apply_filters( 'woocommerce_cart_item_name', $_product->get_name(), $cart_item, $cart_item_key );
$thumbnail = apply_filters( 'woocommerce_cart_item_thumbnail', $_product->get_image(), $cart_item, $cart_item_key );
$product_price = apply_filters( 'woocommerce_cart_item_price', WC()->cart->get_product_price( $_product ), $cart_item, $cart_item_key );
$variation_val = $cart_item['variation']['attribute_pa_size'];
$term_obj = get_term_by('slug', $variation_val, 'pa_size');
$size_name = $term_obj->name;
?>
<div class="media mini-cart__item woocommerce-mini-cart-item <?php echo esc_attr( apply_filters( 'woocommerce_mini_cart_item_class', 'mini_cart_item', $cart_item, $cart_item_key ) ); ?>">
<?php echo $thumbnail; ?>
<div class="media-body mini-cart__item_body">
<div class="mini-cart__item__heading mt-0"><?php echo $product_name; ?></div>
<?php
echo apply_filters( 'woocommerce_widget_cart_item_quantity', '<div class="cart__item__price">' . sprintf( '%s × %s', $cart_item['quantity'], $product_price ) . '</div>', $cart_item, $cart_item_key ); ?>
<div class="mini-cart__item__size"><?php echo $size_name; ?></div>
</div>
<div class="mini-cart__item_remove">
<?php
echo apply_filters( 'woocommerce_cart_item_remove_link', sprintf(
'×',
esc_url( wc_get_cart_remove_url( $cart_item_key ) ),
__( 'Remove this item', 'woocommerce' ),
esc_attr( $product_id ),
esc_attr( $cart_item_key ),
esc_attr( $_product->get_sku() )
), $cart_item_key );
?>
</div>
</div>
<?php } ?>
<?php endforeach; ?>
<span class="btn__text"><?php _e('Checkout', 'frosted'); ?></span>
</div>
<?php
$fragments['a.cart-contents'] = ob_get_clean();
return $fragments;
}
add_filter( 'woocommerce_add_to_cart_fragments', 'my_header_add_to_cart_fragment' );
Looking for an advices and your help.
UPDATE: changed $fragments['a.cart-contents'] = ob_get_clean(); to $fragments['div.widget_shopping_cart_content'] = ob_get_clean(); to make it return right fragment(not two, like on sreenshot), but didn't help
The following will compact your code and will ajax refresh the mini-cart count + the mini-cart content in the right way:
// Utility function that outputs the mini cart content
function my_wc_mini_cart_content(){
$cart = WC()->cart->get_cart();
foreach ( $cart as $cart_item_key => $cart_item ):
$_product = apply_filters( 'woocommerce_cart_item_product', $cart_item['data'], $cart_item, $cart_item_key );
$product_id = apply_filters( 'woocommerce_cart_item_product_id', $cart_item['product_id'], $cart_item, $cart_item_key );
if ( $_product && $_product->exists() && $cart_item['quantity'] > 0 && apply_filters( 'woocommerce_widget_cart_item_visible', true, $cart_item, $cart_item_key ) ) {
$product_name = apply_filters( 'woocommerce_cart_item_name', $_product->get_name(), $cart_item, $cart_item_key );
$thumbnail = apply_filters( 'woocommerce_cart_item_thumbnail', $_product->get_image(), $cart_item, $cart_item_key );
$product_price = apply_filters( 'woocommerce_cart_item_price', WC()->cart->get_product_price( $_product ), $cart_item, $cart_item_key );
if(isset($cart_item['variation']['attribute_pa_size'])) {
$variation_val = $cart_item['variation']['attribute_pa_size'];
$term_obj = get_term_by('slug', $variation_val, 'pa_size');
$size_name = $term_obj->name;
}
?>
<div class="media mini-cart__item woocommerce-mini-cart-item <?php echo esc_attr( apply_filters( 'woocommerce_mini_cart_item_class', 'mini_cart_item', $cart_item, $cart_item_key ) ); ?>">
<?php echo $thumbnail; ?>
<div class="media-body mini-cart__item_body">
<div class="mini-cart__item__heading mt-0"><?php echo $product_name; ?></div>
<?php
echo apply_filters( 'woocommerce_widget_cart_item_quantity', '<div class="cart__item__price">' .
sprintf( '%s × %s', $cart_item['quantity'], $product_price ) .
'</div>', $cart_item, $cart_item_key );
if( isset($size_name) ) { ?>
<div class="mini-cart__item__size"><?php echo $size_name; ?></div>
<?php } ?>
</div>
<div class="mini-cart__item_remove ">
<?php
echo apply_filters( 'woocommerce_cart_item_remove_link', sprintf(
'×',
esc_url( wc_get_cart_remove_url( $cart_item_key ) ),
__( 'Remove this item', 'woocommerce' ),
esc_attr( $product_id ),
esc_attr( $cart_item_key ),
esc_attr( $_product->get_sku() )
), $cart_item_key );
?>
</div>
</div>
<?php
}
endforeach; ?>
<span class="btn__text"><?php _e('Checkout', 'frosted'); ?></span>
<?php
}
// Hooked: The mini cart count and the cart content
add_action( 'frosted_header_top', 'my_wc_mini_cart' );
function my_wc_mini_cart() {
if ( in_array( 'woocommerce/woocommerce.php', apply_filters( 'active_plugins', get_option( 'active_plugins' ) ) ) ) {
$count = WC()->cart->get_cart_contents_count();
?>
<?php _e('Cart', 'frosted'); ?> <span id="cart_count" class="cart__amount"><?php echo esc_html( $count ); ?></span>
<div id="mini-cart-content" class="sub-menu sub-menu--right sub-menu--cart">
<?php my_wc_mini_cart_content(); ?>
</div>
<?php
}
}
// Ajax refreshing mini cart count and content
add_filter( 'woocommerce_add_to_cart_fragments', 'my_header_add_to_cart_fragment' );
function my_header_add_to_cart_fragment( $fragments ) {
$count = WC()->cart->get_cart_contents_count();
$fragments['#cart_count'] = '<span id="cart_count" class="cart__amount">' . esc_attr( $count ) . '</span>';
ob_start();
?>
<div id="mini-cart-content" class="sub-menu sub-menu--right sub-menu--cart">
<?php my_wc_mini_cart_content(); ?>
<div>
<?php
$fragments['#mini-cart-content'] = ob_get_clean();
return $fragments;
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.
After trying to use solution marked as correct answer, the remove function still not worked for me, but I found another solution here.
adding widget_shopping_cart_content classname to my mini-cart's container made it work
I'm generating my cart as such:
if( !is_wp_error( $this->getCartContentsCount() ) ) {
$cart_items = WC()->cart->get_cart();
foreach( $cart_items as $item ) { ?>
<div class="left col-md-3">
<div class="product-image"><!-- Make sure ot check if it's a gallery, if so, get its first image -->
<?php echo $item['data']->get_image(); ?>
</div>
</div>
<div class="right col-md-8">
<h4 class="product-name"><?php echo $item['data']->get_name(); ?></h4>
<div class="product-information">
<span class="product-quantity"><?php echo $item['quantity'] . 'x' ?></span>
<span class="product-price"><?php echo $item['data']->get_price_html(); ?></span>
</div>
<?php
echo apply_filters( 'woocommerce_cart_item_remove_link', sprintf(
'X',
esc_url( wc_get_cart_remove_url( $item ) ),
__( 'Remove this item', 'woocommerce' ),
esc_attr( $item['product_id'] ),
esc_attr( $item['data']->get_sku() )
), $item );
?>
</div>
<?php }
}
As you can see, I'm using the basic Woocommerce implementation of the "remove item" mechanism as per cart.php, but unfortunately, it doesn't work.
This is what Woo generates:
X
I have checked every attribute and it is indeed valid!
Other symptoms:
The link, if accessed directly, takes me to the cart itself (I
believe it is due to the nonce).
Dumping the cart before and after the click still shows the same
cart with just one item in it, so the mechanism to delete doesn't
work as the cart doesn't change its state.
How come it doesn't work?
I actually went ahead and copied the cart.php implementation and customized it to my needs:
ob_start();
if( !is_wp_error( $this->getCartContentsCount() ) ) { //This checks if there are any items in the cart.
foreach( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
$_product = apply_filters(
'woocommerce_cart_item_product',
$cart_item['data'], $cart_item, $cart_item_key
);
$product_id = apply_filters(
'woocommerce_cart_item_product_id',
$cart_item['product_id'], $cart_item, $cart_item_key
);
if ( $_product && $_product->exists() && $cart_item['quantity'] > 0 && apply_filters( 'woocommerce_cart_item_visible', true, $cart_item, $cart_item_key ) ) {
$product_permalink = apply_filters(
'woocommerce_cart_item_permalink',
$_product->is_visible() ? $_product->get_permalink( $cart_item ) : '', $cart_item, $cart_item_key
); ?>
<div class="cart-item <?php echo esc_attr( apply_filters( 'woocommerce_cart_item_class', 'cart_item', $cart_item, $cart_item_key ) ); ?>">
<div class="left col-md-3">
<div class="product-image">
<?php
$thumbnail = apply_filters(
'woocommerce_cart_item_thumbnail',
$_product->get_image(), $cart_item, $cart_item_key
);
if ( !$product_permalink ) {
echo wp_kses_post( $thumbnail );
} else {
printf( '%s', esc_url( $product_permalink ), wp_kses_post( $thumbnail ) );
}
?>
</div>
</div>
<div class="right col-md-8">
<h4 class="product-name">
<?php
if ( ! $product_permalink ) {
echo wp_kses_post( apply_filters(
'woocommerce_cart_item_name',
$_product->get_name(), $cart_item, $cart_item_key ) . ' '
);
} else {
echo wp_kses_post( apply_filters(
'woocommerce_cart_item_name',
sprintf(
'%s',
esc_url( $product_permalink ), $_product->get_name()
), $cart_item, $cart_item_key
)
);
}
// Meta data.
echo wc_get_formatted_cart_item_data( $cart_item ); // PHPCS: XSS ok.
// Backorder notification.
if ( $_product->backorders_require_notification() && $_product->is_on_backorder( $cart_item['quantity'] ) ) {
echo wp_kses_post( apply_filters(
'woocommerce_cart_item_backorder_notification',
'<p class="backorder_notification">' . esc_html__( 'Available on backorder', 'woocommerce' ) . '</p>'
)
);
}
?>
</h4>
<div class="product-information">
<div class="product-quantity">
<?php
$product_quantity = sprintf(
'%s<input type="hidden" name="cart[%s][qty]" value="%s" />',
$cart_item['quantity'], $cart_item_key, $cart_item['quantity']
);
echo apply_filters(
'woocommerce_cart_item_quantity',
$product_quantity, $cart_item_key, $cart_item
); // PHPCS: XSS ok.
?>
</div>
<div class="product-price">
<?php
echo apply_filters(
'woocommerce_cart_item_price',
WC()->cart->get_product_price( $_product ), $cart_item, $cart_item_key ); // PHPCS: XSS ok.
?>
</div>
</div>
<div class="product-remove">
<?php
echo apply_filters( 'woocommerce_cart_item_remove_link', sprintf(
'×',
esc_url( wc_get_cart_remove_url( $cart_item_key ) ),
__( 'Remove this item', 'woocommerce' ),
esc_attr( $product_id ),
esc_attr( $_product->get_sku() )
), $cart_item_key );
?>
</div>
</div>
</div>
<?php
}
}
}
$markup_output = ob_get_contents();
ob_end_clean();
echo $markup_output;
Simple use this WC_Cart::remove_cart_item( $cart_item_key );