After moving to Woocommerce, we've built a page that showing several categories and all the products of each of these categories. The idea is to allow a customer to build their own product.
We've got the categories and products showing with their name, image, a price, add to cart and quantity field aside each product.
We'd like to add the flexibility for the page to display a total calculation of all their selections and provide an 'Add All Selections to Cart' type of button, is this possible?
I'll outline what we've done so far in case more details are needed. To get the 'add to cart' to appear next to each product we used a modified version of the following 'override loop template...' as follows:
<?php
/**
* Loop Add to Cart
*
* #author WooThemes
* #package WooCommerce/Templates
* #version 2.2.0
*/
if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
global $product;
$mode = get_option('catalog_mode');
?>
<?php if ( ! $product->is_in_stock() || $mode == 'on' ) : ?>
<?php echo apply_filters( 'out_of_stock_add_to_cart_text', __( 'Read More', 'woocommerce' ) ); ?>
<?php else : ?>
<?php
$link = array(
'url' => '',
'label' => '',
'class' => ''
);
$handler = apply_filters( 'woocommerce_add_to_cart_handler', $product->product_type, $product );
switch ( $handler ) {
case "variable" :
$link['url'] = apply_filters( 'variable_add_to_cart_url', get_permalink( $product->id ) );
$link['label'] = apply_filters( 'variable_add_to_cart_text', __( 'Select options', 'woocommerce' ) );
break;
case "grouped" :
$link['url'] = apply_filters( 'grouped_add_to_cart_url', get_permalink( $product->id ) );
$link['label'] = apply_filters( 'grouped_add_to_cart_text', __( 'View options', 'woocommerce' ) );
break;
case "external" :
$link['url'] = apply_filters( 'external_add_to_cart_url', get_permalink( $product->id ) );
$link['label'] = apply_filters( 'external_add_to_cart_text', __( 'Read More', 'woocommerce' ) );
break;
default :
if ( $product->is_purchasable() ) {
$link['url'] = apply_filters( 'add_to_cart_url', esc_url( $product->add_to_cart_url() ) );
$link['label'] = apply_filters( 'add_to_cart_text', __( 'Add to cart', 'woocommerce' ) );
$link['class'] = apply_filters( 'add_to_cart_class', 'add_to_cart_button' );
} else {
$link['url'] = apply_filters( 'not_purchasable_url', get_permalink( $product->id ) );
$link['label'] = apply_filters( 'not_purchasable_text', __( 'Read More', 'woocommerce' ) );
}
break;
}
//EDIT for Add to Cart
//printf('%s', $link, $product->id, $product->product_type, $label);
if ( $product->product_type == 'simple' ) {
?>
<form action="<?php echo esc_url( $product->add_to_cart_url() ); ?>" class="cart" method="post" enctype='multipart/form-data'>
<?php woocommerce_quantity_input(); ?>
<button type="submit" class="button alt"><?php echo $label; ?></button>
</form>
<?php
} else {
printf('%s', $link, $product->id, $product->product_type, $label);
}
//END Add to Cart
echo apply_filters( 'woocommerce_loop_add_to_cart_link', sprintf('%s', esc_url( $link['url'] ), esc_attr( $product->id ), esc_attr( $product->get_sku() ), esc_attr( $link['class'] ), esc_attr( $product->product_type ), esc_html( $link['label'] ) ), $product, $link );
?>
Finally, we added the categories to the page and showed their products by adding a few of the following to a page template:
<ul class="products">
<?php
$args = array( 'post_type' => 'product', 'posts_per_page' => -1, 'product_cat' => 'INSERT CATEGORY HERE', 'orderby' => 'rand' );
$loop = new WP_Query( $args );
while ( $loop->have_posts() ) : $loop->the_post(); global $product; ?>
<li class="product">
<a href="<?php echo get_permalink( $loop->post->ID ) ?>" title="<?php echo esc_attr($loop->post->post_title ? $loop->post->post_title : $loop->post->ID); ?>">
<?php woocommerce_show_product_sale_flash( $post, $product ); ?>
<?php if (has_post_thumbnail( $loop->post->ID )) echo get_the_post_thumbnail($loop->post->ID, 'shop_catalog'); else echo '<img src="'.woocommerce_placeholder_img_src().'" alt="Placeholder" width="300px" height="300px" />'; ?>
<h3><?php the_title(); ?></h3>
<span class="price"><?php echo $product->get_price_html(); ?></span>
</a>
<?php woocommerce_template_loop_add_to_cart( $loop->post, $product ); ?>
</li>
<?php endwhile; ?>
<?php wp_reset_query(); ?>
</ul><!--/.products-->
<!--End Display Products-->
This could apply to anyone building out separate products for a brand. We're not into building cars, but say we were, the desired workflow is relatively the same for any series of products - if cars were the case, what we'd be trying to complete is a functional place a build your own car for each model on their own pages.
To break down each model, we've categorized parts of the car, that might interest that car consumer, into categories; so we might have a category that is composed of wheels and tires for X car and another category for wheels and tires for Y car.
Let's say we're writing the page build car x. We would like them to be able to select all the quantities of all applicable products that compose 'car x'. To do so, we have displayed all the categories that apply to car x, and all the products in said categories. We have a quantity field and add to cart next to the quantity.
We would like to get that to total and allow for an add all selections to cart button at the bottom of the page.
Related
In WooCommerce, I'm trying to add some custom code into my active theme's functions.php file, which will enable for variable products to display the attribute dropdowns, the quantity field and the add to cart button on shop and archive pages.
Here's my actual code:
// Display variations dropdowns on shop page for variable products
add_filter( 'woocommerce_loop_add_to_cart_link', 'woo_display_variation_dropdown_on_shop_page' );
function woo_display_variation_dropdown_on_shop_page() {
global $product;
if( $product->is_type( 'variable' )) {
$attribute_keys = array_keys( $product->get_attributes() );
?>
<form class="variations_form cart" method="post" enctype='multipart/form-data' data-product_id="<?php echo absint( $product->id ); ?>" data-product_variations="<?php echo htmlspecialchars( json_encode( $product->get_available_variations() ) ) ?>">
<?php do_action( 'woocommerce_before_variations_form' ); ?>
<?php if ( empty( $product->get_available_variations() ) && false !== $product->get_available_variations() ) : ?>
<p class="stock out-of-stock"><?php _e( 'This product is currently out of stock and unavailable.', 'woocommerce' ); ?></p>
<?php else : ?>
<table class="variations" cellspacing="0">
<tbody>
<?php foreach ( $product->get_attributes() as $attribute_name => $options ) : ?>
<tr>
<td class="label"><label for="<?php echo sanitize_title( $attribute_name ); ?>"><?php echo wc_attribute_label( $attribute_name ); ?></label></td>
<td class="value">
<?php
$selected = isset( $_REQUEST[ 'attribute_' . sanitize_title( $attribute_name ) ] ) ? wc_clean( urldecode( $_REQUEST[ 'attribute_' . sanitize_title( $attribute_name ) ] ) ) : $product->get_variation_default_attribute( $attribute_name );
wc_dropdown_variation_attribute_options( array( 'options' => $options, 'attribute' => $attribute_name, 'product' => $product, 'selected' => $selected ) );
echo end( $attribute_keys ) === $attribute_name ? apply_filters( 'woocommerce_reset_variations_link', '<a class="reset_variations" href="#">' . __( 'Clear', 'woocommerce' ) . '</a>' ) : '';
?>
</td>
</tr>
<?php endforeach;?>
</tbody>
</table>
<?php do_action( 'woocommerce_before_add_to_cart_button' ); ?>
<div class="single_variation_wrap">
<?php
/**
* woocommerce_before_single_variation Hook.
*/
do_action( 'woocommerce_before_single_variation' );
/**
* woocommerce_single_variation hook. Used to output the cart button and placeholder for variation data.
* #since 2.4.0
* #hooked woocommerce_single_variation - 10 Empty div for variation data.
* #hooked woocommerce_single_variation_add_to_cart_button - 20 Qty and cart button.
*/
do_action( 'woocommerce_single_variation' );
/**
* woocommerce_after_single_variation Hook.
*/
do_action( 'woocommerce_after_single_variation' );
?>
</div>
<?php do_action( 'woocommerce_after_add_to_cart_button' ); ?>
<?php endif; ?>
<?php do_action( 'woocommerce_after_variations_form' ); ?>
</form>
<?php } else {
echo sprintf( '<a rel="nofollow" href="%s" data-quantity="%s" data-product_id="%s" data-product_sku="%s" class="%s">%s</a>',
esc_url( $product->add_to_cart_url() ),
esc_attr( isset( $quantity ) ? $quantity : 1 ),
esc_attr( $product->id ),
esc_attr( $product->get_sku() ),
esc_attr( isset( $class ) ? $class : 'button' ),
esc_html( $product->add_to_cart_text() )
);
}
}
But the following errors are thrown and having issues making it work:
Your PHP code changes were rolled back due to an error on line 666 of file wp-content/plugins/woocommerce-composite-products/includes/wc-cp-template-functions.php. Please fix and try saving again.
Uncaught Error: Call to a member function get_type() on null in
wp-content/plugins/woocommerce-composite-products/includes/wc-cp-template-functions.php:666
Stack trace:
#0 wp-includes/class-wp-hook.php(286): wc_cp_before_add_to_cart_button('')
#1 wp-includes/class-wp-hook.php(310): WP_Hook->apply_filters('', Array)
#2 wp-includes/plugin.php(465): WP_Hook->do_action(Array)
#3 wp-content/themes/electro-child/functions.php(2228): do_action('woocommerce_bef...')
#4 wp-includes/class-wp-hook.php(288): woo_display_variation_dropdown_on_shop_page('<a href="https:...')
#5 wp-includes/plugin.php(208): WP_Hook->apply_filters('<a href="https:...', Array)
#6 wp-content/plugins/woocommerce/templates/loop/add
I think there's a conflict with the Composite product plugin I'm using.
Any help is hugely appreciated.
The biggest mistake in your code is that you just forgot that you are using a filter hook and in that case, you need to return the output, but not to echo it.
Then you will use the hook arguments that are included in this filter hook instead.
Also you just need to change the behavior for variable products only, because, with your actual code, as you are also using the WooCommerce Composite Products plugin, it gives you the reported error.
So try instead something like (untested):
// Display variations dropdowns on shop page for variable products
add_filter( 'woocommerce_loop_add_to_cart_link', 'woo_display_variation_dropdown_on_shop_page', 10, 3 );
function woo_display_variation_dropdown_on_shop_page( $add_to_cart_link, $product, $args ) {
if( $product->is_type('variable') ) {
$attribute_keys = array_keys( $product->get_attributes() );
ob_start(); // Start buffering
?>
<form class="variations_form cart" method="post" enctype='multipart/form-data' data-product_id="<?php echo absint( $product->id ); ?>" data-product_variations="<?php echo htmlspecialchars( json_encode( $product->get_available_variations() ) ) ?>">
<?php do_action( 'woocommerce_before_variations_form' ); ?>
<?php if ( empty( $product->get_available_variations() ) && false !== $product->get_available_variations() ) : ?>
<p class="stock out-of-stock"><?php _e( 'This product is currently out of stock and unavailable.', 'woocommerce' ); ?></p>
<?php else : ?>
<table class="variations" cellspacing="0">
<tbody>
<?php foreach ( $product->get_attributes() as $attribute_name => $options ) : ?>
<tr>
<td class="label"><label for="<?php echo sanitize_title( $attribute_name ); ?>"><?php echo wc_attribute_label( $attribute_name ); ?></label></td>
<td class="value">
<?php
$selected = isset( $_REQUEST[ 'attribute_' . sanitize_title( $attribute_name ) ] ) ? wc_clean( urldecode( $_REQUEST[ 'attribute_' . sanitize_title( $attribute_name ) ] ) ) : $product->get_variation_default_attribute( $attribute_name );
wc_dropdown_variation_attribute_options( array( 'options' => $options, 'attribute' => $attribute_name, 'product' => $product, 'selected' => $selected ) );
echo end( $attribute_keys ) === $attribute_name ? apply_filters( 'woocommerce_reset_variations_link', '<a class="reset_variations" href="#">' . __( 'Clear', 'woocommerce' ) . '</a>' ) : '';
?>
</td>
</tr>
<?php endforeach;?>
</tbody>
</table>
<?php do_action( 'woocommerce_before_add_to_cart_button' ); ?>
<div class="single_variation_wrap">
<?php
/**
* woocommerce_before_single_variation Hook.
*/
do_action( 'woocommerce_before_single_variation' );
/**
* woocommerce_single_variation hook. Used to output the cart button and placeholder for variation data.
* #since 2.4.0
* #hooked woocommerce_single_variation - 10 Empty div for variation data.
* #hooked woocommerce_single_variation_add_to_cart_button - 20 Qty and cart button.
*/
do_action( 'woocommerce_single_variation' );
/**
* woocommerce_after_single_variation Hook.
*/
do_action( 'woocommerce_after_single_variation' );
?>
</div>
<?php do_action( 'woocommerce_after_add_to_cart_button' ); ?>
<?php endif; ?>
<?php do_action( 'woocommerce_after_variations_form' ); ?>
</form>
<?php
$add_to_cart_link = ob_get_clean(); // The buffered content
}
return $add_to_cart_link;
}
I am trying to display the count of the items in the cart at the bottom or top of the Woocommerce cart widget. It seems that by default behaviour the cart widget does not do this when in the sidebar.
I have researched SO and found the following answer, but it has a slightly different goal of adding individual subtotals. I have tried modifying it, by passing in WC()->cart->get_cart_contents_count() instead of WC()->cart->get_cart() to see if I can get the cart item count, but it's not displaying...any suggestions?
Example of what I am trying to do:
Code I have modified from the approved answer:
<?php
/**
* Mini-cart
*
* Contains the markup for the mini-cart, used by the cart widget
*
* #author WooThemes
* #package WooCommerce/Templates
* #version 2.1.0
*/
if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
?>
<?php do_action( 'woocommerce_before_mini_cart' ); ?>
<ul class="cart_list product_list_widget <?php echo $args['list_class']; ?>">
<?php if ( WC()->cart->get_cart_contents_count() ) > 0 ) : ?>
<?php
foreach ( WC()->cart->get_cart_contents_count() 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_title(), $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 );
echo "<p>".$product_price."</p>";
?>
<li>
<?php if ( ! $_product->is_visible() ) { ?>
<?php echo str_replace( array( 'http:', 'https:' ), '', $thumbnail ) . $product_name; ?>
<?php } else { ?>
<a href="<?php echo get_permalink( $product_id ); ?>">
<?php echo str_replace( array( 'http:', 'https:' ), '', $thumbnail ) . $product_name; ?>
</a>
<?php } ?>
<?php echo WC()->cart->get_item_data( $cart_item ); ?>
<?php $new_product_price_array = explode ( get_woocommerce_currency_symbol(), $product_price);
$new_product_price = number_format((float)$new_product_price_array[1] * $cart_item['quantity'], 2, '.', '');
?>
<?php echo apply_filters( 'woocommerce_widget_cart_item_quantity', '<span class="quantity">' . sprintf( '%s × %s=%s%s', $cart_item['quantity'], $product_price,get_woocommerce_currency_symbol(), $new_product_price ) . '</span>', $cart_item, $cart_item_key ); ?>
</li>
<?php
}
}
?>
<?php else : ?>
<li class="empty"><?php _e( 'No products in the cart.', 'woocommerce' ); ?></li>
<?php endif; ?>
</ul><!-- end product list -->
<?php if ( WC()->cart->get_cart_contents_count() ) > 0 ) : ?>
<p class="total"><strong><?php _e( 'Subtotal', 'woocommerce' ); ?>:</strong> <?php echo WC()->cart->get_cart_subtotal(); ?></p>
<?php do_action( 'woocommerce_widget_shopping_cart_before_buttons' ); ?>
<p class="buttons">
<?php _e( 'View Cart', 'woocommerce' ); ?>
<?php _e( 'Checkout', 'woocommerce' ); ?>
</p>
<?php endif; ?>
<?php do_action( 'woocommerce_after_mini_cart' ); ?>
If you want to display the cart item count in the mini cart widget you can use hooks:
1) On top before minicart content:
add_action( 'woocommerce_before_mini_cart', 'minicart_count_after_content' );
function minicart_count_after_content() {
$items_count = WC()->cart->get_cart_contents_count();
$text_label = _n( 'Item', 'Items', $items_count, 'woocommerce' );
?>
<p class="total item-count"><strong><?php echo $text_label; ?>:</strong> <?php echo $items_count; ?></p>
<?php
}
2) On the bottom before the buttons:
add_action( 'woocommerce_widget_shopping_cart_before_buttons', 'minicart_count_before_content' );
function minicart_count_before_content() {
$items_count = WC()->cart->get_cart_contents_count();
$text_label = _n( 'Item', 'Items', $items_count, 'woocommerce' );
?>
<p class="total item-count"><strong><?php echo $text_label; ?>:</strong> <?php echo $items_count; ?></p>
<?php
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.
WC()->cart->get_cart_contents_count(); will give you the total items count including quantities.
If you want to get the number of items in cart you will use instead:
$items_count = sizeof( WC()->cart->get_cart() );
You aren't echoing WC()->cart->get_cart_contents_count() anywhere, so no, it won't display.
Wherever in the code you need to display the count, you'll need to use
echo WC()->cart->get_cart_contents_count();
I have no idea of php so I was wondering if I can get help from you guys.
So basically this is my code for woocommerce minicart.
Right now when I click on a single item to buy twice the cart counter stays on 1, when instead I obviously want 2 as it is the total.
I am aware of the things saying here, but I can't seem to find where to put the code. I tried everything and I can't make those totals to show up.
If someone can tell me which part exactly should be changed I would very much appreciate it. Thanks in advance!
<?php
/**
* Mini-cart
*
* Contains the markup for the mini-cart, used by the cart widget.
*
* This template can be overridden by copying it to yourtheme/woocommerce/cart/mini-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 http://docs.woothemes.com/document/template-structure/
* #author WooThemes
* #package WooCommerce/Templates
* #version 2.5.0
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
}
?>
<?php do_action( 'woocommerce_before_mini_cart' ); ?>
<ul class="cart_list products-list product_list_widget <?php echo $args['list_class']; ?>">
<?php if ( ! WC()->cart->is_empty() ) : ?>
<?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_widget_cart_item_visible', true, $cart_item, $cart_item_key ) ) {
$product_name = apply_filters( 'woocommerce_cart_item_name', $_product->get_title(), $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 );
?>
<li>
<?php if ( ! $_product->is_visible() ) : ?>
<?php echo str_replace( array( 'http:', 'https:' ), '', $thumbnail ) . $product_name . ' '; ?>
<?php else : ?>
<a class="title" href="<?php echo esc_url( $_product->get_permalink( $cart_item ) ); ?>">
<?php echo str_replace( array( 'http:', 'https:' ), '', $thumbnail ) . $product_name . ' '; ?>
</a>
<?php endif; ?>
<?php echo WC()->cart->get_item_data( $cart_item ); ?>
<?php echo apply_filters( 'woocommerce_widget_cart_item_quantity', '<span class="quantity">' . sprintf( '%s × %s', $cart_item['quantity'], $product_price ) . '</span>', $cart_item, $cart_item_key ); ?>
<?php echo apply_filters( 'woocommerce_cart_item_remove_link', sprintf( '<i class="fa fa-times-circle"></i>', esc_url( WC()->cart->get_remove_url( $cart_item_key ) ), __( 'Remove this item', 'snssimen' ) ), $cart_item_key ); ?>
</li>
<?php
}
}
?>
<?php else : ?>
<li class="empty"><?php _e( 'No products in the cart.', 'snssimen' ); ?></li>
<?php endif; ?>
</ul><!-- end product list -->
<?php if ( sizeof( WC()->cart->get_cart() ) > 0 ) : ?>
<p class="total"><?php _e( 'Total', 'snssimen' ); ?>: <strong><?php echo WC()->cart->get_cart_subtotal(); ?></strong></p>
<?php do_action( 'woocommerce_widget_shopping_cart_before_buttons' ); ?>
<p class="buttons">
<?php _e( 'Go to Cart', 'snssimen' ); ?>
<?php _e( 'Checkout', 'snssimen' ); ?>
</p>
<span style="display:none" class="sns-cart-number">
<?php echo sizeof( WC()->cart->get_cart() ) ?>
<?php //echo $woocommerce->cart->cart_contents_count; ?>
</span>
<?php endif; ?>
<?php do_action( 'woocommerce_after_mini_cart' ); ?>
In WooCommerce, my products are listed in category page with details as well as "Add to Cart" button. When user clicked on the button page refreshed and on the top success message with view cart button appeared.
when a user does it for multiple times(add more than one items):
If the user is logged in the cart page listed all the items with calculation.
but if the user is not logged in, the user only see the last item listed in cart page.
I need to list the cart added products for not logged in user..Can anyone have the solution for this...
Here is my loop/add-to-cart.php code:
echo apply_filters( 'woocommerce_loop_add_to_cart_link',
sprintf( '%s',
esc_url( $product->add_to_cart_url() ),
esc_attr( $product->id ),
esc_attr( $product->get_sku() ),
esc_attr( isset( $quantity ) ? $quantity : 1 ),
$product->is_purchasable() && $product->is_in_stock() ? 'add_to_cart_button' : '',
esc_attr( $product->product_type ),
esc_html( $product->add_to_cart_text() )
),
$product );
Updated and checked the code (2)
Cart count works and cart page displays only last cart item for non logged users
1) When you are not logged in, only last cart item is displayed.
2) When you are logged in, all cart items are displayed.
This is possible editing the woocommerce cart.php template.
You will need first to copy to your active child theme (or theme) folder, the WooCommerce templates folder located in your woocommerce plugin folder (if not done yet) and rename that newly added folder woocommerce. See this related documentation.
Once done, you will open edit cart/cart.php file and replace the code by the following:
<?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/
* #author WooThemes
* #package WooCommerce/Templates
* #version 2.3.8
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
}
wc_print_notices();
do_action( 'woocommerce_before_cart' ); ?>
<form action="<?php echo esc_url( wc_get_cart_url() ); ?>" method="post">
<?php do_action( 'woocommerce_before_cart_table' );
// Cart count
$the_cart = WC()->cart->get_cart_contents_count();
// initialising counter for the loop (out of it)
$count = 0;
// CHECKING JUST THE CART COUNT - TO BE REMOVED
echo '<p style="font-style:italic; color: grey; margin:10px;">(Debug Info only - Cart count: <strong>'. WC()->cart->get_cart_contents_count() . '</strong> item(s))</p>';
?>
<table class="shop_table shop_table_responsive cart" cellspacing="0">
<thead>
<tr>
<th class="product-remove"> </th>
<th class="product-thumbnail"> </th>
<th class="product-name"><?php _e( 'Product', 'woocommerce' ); ?></th>
<th class="product-price"><?php _e( 'Price', 'woocommerce' ); ?></th>
<th class="product-quantity"><?php _e( 'Quantity', 'woocommerce' ); ?></th>
<th class="product-subtotal"><?php _e( 'Total', 'woocommerce' ); ?></th>
</tr>
</thead>
<tbody>
<?php do_action( 'woocommerce_before_cart_contents' ); ?>
<?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( is_user_logged_in() || ( !is_user_logged_in() && $count == $cart_count) ):
// adding 1 to counter
$count++;
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="<?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( 'woocommerce_cart_item_remove_link', sprintf(
'×',
esc_url( WC()->cart->get_remove_url( $cart_item_key ) ),
__( '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;
} else {
printf( '%s', esc_url( $product_permalink ), $thumbnail );
}
?>
</td>
<td class="product-name" data-title="<?php _e( 'Product', 'woocommerce' ); ?>">
<?php
if ( ! $product_permalink ) {
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', esc_url( $product_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', 'woocommerce' ) . '</p>';
}
?>
</td>
<td class="product-price" data-title="<?php _e( 'Price', 'woocommerce' ); ?>">
<?php
echo apply_filters( 'woocommerce_cart_item_price', WC()->cart->get_product_price( $_product ), $cart_item, $cart_item_key );
?>
</td>
<td class="product-quantity" data-title="<?php _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->backorders_allowed() ? '' : $_product->get_stock_quantity(),
'min_value' => '0'
), $_product, false );
}
echo apply_filters( 'woocommerce_cart_item_quantity', $product_quantity, $cart_item_key, $cart_item );
?>
</td>
<td class="product-subtotal" data-title="<?php _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 );
?>
</td>
</tr>
<?php
}
endif;
}
do_action( 'woocommerce_cart_contents' );
?>
<tr>
<td colspan="6" class="actions">
<?php if ( wc_coupons_enabled() ) { ?>
<div class="coupon">
<label for="coupon_code"><?php _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' ); ?>" /> <input type="submit" class="button" name="apply_coupon" value="<?php esc_attr_e( 'Apply Coupon', 'woocommerce' ); ?>" />
<?php do_action( 'woocommerce_cart_coupon' ); ?>
</div>
<?php } ?>
<input type="submit" class="button" name="update_cart" value="<?php esc_attr_e( 'Update Cart', 'woocommerce' ); ?>" />
<?php do_action( 'woocommerce_cart_actions' ); ?>
<?php wp_nonce_field( 'woocommerce-cart' ); ?>
</td>
</tr>
<?php do_action( 'woocommerce_after_cart_contents' ); ?>
</tbody>
</table>
<?php do_action( 'woocommerce_after_cart_table' ); ?>
</form>
<div class="cart-collaterals">
<?php do_action( 'woocommerce_cart_collaterals' ); ?>
</div>
<?php do_action( 'woocommerce_after_cart' ); ?>
Then save.
As you will see on line 31 to 38 (outside the cat foreach loop), I have added some code to get the total cart items count and initialized a counter to zero. Also I have temporarily displayed the cart count (You can remove this line as it's only for testing).
I have add a conditional if statement that is going to do what you are expecting:
if( is_user_logged_in() || ( !is_user_logged_in() && $count == $cart_count) ):
Just after this condition I increment the $count variable (which is in the condition).
This is tested and works perfectly now…
I am using WooCommerce mini cart widget and I want to limit the number of products shown in the mini cart. If a user adds 10 products to the cart, the mini cart widget shows all 10.
I would like to limit the number lets say to 5 products.
Is there a way to achieve this?
Thanks.
You can achieve this overriding cart/mini-cart.php WooCommerce template via your active theme, ( see this related docs: Template Structure + Overriding Templates via a Theme ).
Briefly (if not done yet), you will need to copy from woocommerce plugin folder, a subfolder named templates to your active child theme (or theme) and to rename it woocommerce..
After that you find inside that new woocommerce folder in cart subfolder a template named mini-cart.php.
Open/edit mini-cart.php template and replace the code by this to limit cart to 5 items:
<?php
/**
* Mini-cart
*
* Contains the markup for the mini-cart, used by the cart widget.
*
* This template can be overridden by copying it to yourtheme/woocommerce/cart/mini-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/
* #author WooThemes
* #package WooCommerce/Templates
* #version 2.5.0
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
}
?>
<?php do_action( 'woocommerce_before_mini_cart' ); ?>
<ul class="cart_list product_list_widget <?php echo $args['list_class']; ?>">
<?php if ( ! WC()->cart->is_empty() ) : ?>
<?php
// Define HERE the number of items
$number_of_items = 5;
$loop_count = 0;
foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
// Limiting number of items displayed in mini cart
if($loop_count < $number_of_items) {
// The counter
$loop_count++;
$_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_title(), $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="<?php echo esc_attr( apply_filters( 'woocommerce_mini_cart_item_class', 'mini_cart_item', $cart_item, $cart_item_key ) ); ?>">
<?php
echo apply_filters( 'woocommerce_cart_item_remove_link', sprintf(
'×',
esc_url( WC()->cart->get_remove_url( $cart_item_key ) ),
__( 'Remove this item', 'woocommerce' ),
esc_attr( $product_id ),
esc_attr( $_product->get_sku() )
), $cart_item_key );
?>
<?php if ( ! $_product->is_visible() ) : ?>
<?php echo str_replace( array( 'http:', 'https:' ), '', $thumbnail ) . $product_name . ' '; ?>
<?php else : ?>
<a href="<?php echo esc_url( $product_permalink ); ?>">
<?php echo str_replace( array( 'http:', 'https:' ), '', $thumbnail ) . $product_name . ' '; ?>
</a>
<?php endif; ?>
<?php echo WC()->cart->get_item_data( $cart_item ); ?>
<?php echo apply_filters( 'woocommerce_widget_cart_item_quantity', '<span class="quantity">' . sprintf( '%s × %s', $cart_item['quantity'], $product_price ) . '</span>', $cart_item, $cart_item_key ); ?>
</li>
<?php
}
}
}
?>
<?php else : ?>
<li class="empty"><?php _e( 'No products in the cart.', 'woocommerce' ); ?></li>
<?php endif; ?>
</ul><!-- end product list -->
<?php if ( ! WC()->cart->is_empty() ) : ?>
<p class="total"><strong><?php _e( 'Subtotal', 'woocommerce' ); ?>:</strong> <?php echo WC()->cart->get_cart_subtotal(); ?></p>
<?php do_action( 'woocommerce_widget_shopping_cart_before_buttons' ); ?>
<p class="buttons">
<?php _e( 'View Cart', 'woocommerce' ); ?>
<?php _e( 'Checkout', 'woocommerce' ); ?>
</p>
<?php endif; ?>
<?php do_action( 'woocommerce_after_mini_cart' ); ?>
Here we count the number of items in the foreach loop and we limit them to a specified number in variable $number_of_items.