I have a menu item that points to the cart and that reads the number of products currently in the cart.
CART (3)
When, on the cart page, I change the number of products and click the "Update cart" button, or delete an item, the number doesn't refresh.
Any idea why?
/*CHANGE CART MENU TITLE IN MENU*/
add_filter( 'wp_setup_nav_menu_item','my_item_setup' );
function my_item_setup($item) {
if ( ! is_admin() ) {
if ( class_exists( 'woocommerce' ) ) {
global $woocommerce;
if ( $item->url == esc_url( wc_get_cart_url() ) ) {
if (is_null($woocommerce->cart)){
} else {
if( get_locale() == 'fr_FR' ) {
$item->title = 'PANIER ('. '<span class="count-cart">' . $woocommerce->cart->get_cart_contents_count() . '</span>)';
} else {
$item->title = 'MY CART ('. '<span class="count-cart">' . $woocommerce->cart->get_cart_contents_count() . '</span>)';
}
}
}
}
}
return $item;
}
And
add_filter( 'woocommerce_add_to_cart_fragments', 'my_woocommerce_add_to_cart_fragments' );
function my_woocommerce_add_to_cart_fragments( $fragments ) {
// Add our fragment
$fragments['li.menu-item-type-woocommerce-cart'] = my_item_setup( '');
return $fragments;
}
EDIT:
Using Ajaxify the cart items count in Woocommerce answer code, seems to work a little better. The product number updates when I delete an item from the cart page, or when I change the number of items, but it doesn't update when I empty the cart. Moreover, there's a space before and after the product number (see picture with empty cart and "CART ( 1 )".
add_filter( 'woocommerce_add_to_cart_fragments', 'wc_refresh_cart_fragments');
function wc_refresh_cart_fragments($fragments){
ob_start();
?>
<span class="count-cart"><?php echo WC()->cart->get_cart_contents_count(); ?></span>
<?php
$fragments['li a span.count-cart'] = ob_get_clean();
return $fragments;
}
Updated
It's better to set a tag ID than a tag CLASS to ajaxify a cart count, as this selector reference need to be unique. If it's not the case, and there is a hidden mobile duplicated menu, it can't work.
So this item menu need to be unique on the generated html code of your pageā¦ If this menu item is duplicated in a mobile version, you will need to change the tag ID or the tag CLASS for the mobile code version.
I have revisited your code a bit:
add_filter( 'wp_setup_nav_menu_item','my_item_setup' );
function my_item_setup( $item ) {
if ( ! is_admin() && class_exists( 'woocommerce' ) ) {
if ( $item->url == esc_url( wc_get_cart_url() ) && ! WC()->cart->is_empty() ){
$title = get_locale() == 'fr_FR' ? 'PANIER' : 'MY CART';
$item->title = $title . ' (<span id="count-cart-items">' . WC()->cart->get_cart_contents_count() . '</span>)';
}
}
return $item;
}
add_filter( 'woocommerce_add_to_cart_fragments', 'wc_refresh_cart_fragments', 50, 1 );
function wc_refresh_cart_fragments( $fragments ){
$cart_count = WC()->cart->get_cart_contents_count();
// Normal version
$count_normal = '<span id="count-cart-items">' . $cart_count . '</span>';
$fragments['#count-cart-items'] = $count_normal;
// Mobile version
$count_mobile = '<span id="count-cart-itemob">' . $cart_count . '</span>';
$fragments['#count-cart-itemob'] = $count_mobile;
return $fragments;
}
Code goes in function.php file of your active child theme (active theme). It should better work.
To Ajaxify your cart viewer so it updates when an item is added or deleted (via ajax) use:
/**
* Show cart contents / total Ajax
*/
add_filter( 'woocommerce_add_to_cart_fragments', 'woocommerce_header_add_to_cart_fragment' );
function woocommerce_header_add_to_cart_fragment( $fragments ) {
global $woocommerce;
ob_start();
?>
<a class="cart-customlocation" href="<?php echo esc_url(wc_get_cart_url()); ?>" title="<?php _e('View your shopping cart', 'woothemes'); ?>"><?php echo sprintf(_n('%d item', '%d items', $woocommerce->cart->cart_contents_count, 'woothemes'), $woocommerce->cart->cart_contents_count);?> - <?php echo $woocommerce->cart->get_cart_total(); ?></a>
<?php
$fragments['a.cart-customlocation'] = ob_get_clean();
return $fragments;
} ?>
Reference Link
Related
I'm trying to crate a snipped to display a second "add to cart" button on all product single pages from a specific categorie. This button should add 6 of the current product to the cart.
UPDATE:
With the info from #kmclaws and here additional add to cart button with fixed quantity in woocommerce single product pages I was able to get this to work. The only problem now is, that the IF in order to only display on "biere" product category does not work.
Problem:
Some Products are from "biere" or "cider" only and some are from "biere" AND "cider" and have some other categories. Means, sometime there are more than one sometime only one category is defined. We want to display this always if "biere" OR/AND "cider" is one of the product category.
How can I code it that way, that if "biere" OR "cider" is the categorie to display that all?
This is my current code:
add_action( 'woocommerce_after_add_to_cart_button', 'additional_simple_add_to_cart', 20 );
function additional_simple_add_to_cart() {
global $product;
// Only for simple product type
if( ! $product->is_type('simple') ) return;
// Only for products from category "biere" AND/OR "Cider"
if ( has_term( 'biere', 'cider', 'product_cat' ) ) {
// Output Info text for "biere" or "cider" products
echo '<p class="rtrn">Infotext block</p>';
// Only display when more than 6 are available
if( $product->get_stock_quantity() >= 6 ) {
$href = '?add-to-cart=' . esc_attr( $product->get_id() ) . '&quantity=6';
$class = 'ingle_add_to_cart_button-12 button alt';
$style = 'display: inline-block; margin-top: 12px;';
$button_text = __( "6 Pack bestellen", "woocommerce" );
// Output add to cart button
echo '<br><a rel="no-follow" href="'.$href.'" class="'.$class.'" style="'.$style.'">'.$button_text.'</a>';
}
}
}
Thanks
It looks like you are not grabbing the ID of the current product in PHP correctly. Try this:
add_action( 'woocommerce_after_add_to_cart_quantity', 'add_quantity_6' );
function add_quantity_6() {
global $product;
$id = $product->get_id();
if ( is_product_category( 'jeans' ) ) {
echo 'Add 6 to Cart';
}
}
You need to replace example.com with either a static or relative path to your site
This is my solutions:
add_action( 'woocommerce_after_add_to_cart_button', 'additional_simple_add_to_cart', 20 );
function additional_simple_add_to_cart() {
global $product;
// Only for simple product type
if( ! $product->is_type('simple') ) return;
// Only for products from category "biere" AND/OR "Cider"
if ( has_term( array('biere', 'cider'), 'product_cat', $product->get_id() ) ) {
// Output Info text for "biere" or "cider" products
echo '<p class="rtrn">Infotext block</p>';
// Only display when more than 6 are available
if( $product->get_stock_quantity() >= 6 ) {
$href = '?add-to-cart=' . esc_attr( $product->get_id() ) . '&quantity=6';
$class = 'ingle_add_to_cart_button-12 button alt';
$style = 'display: inline-block; margin-top: 12px;';
$button_text = __( "6 Pack bestellen", "woocommerce" );
// Output add to cart button
echo '<br><a rel="no-follow" href="'.$href.'" class="'.$class.'" style="'.$style.'">'.$button_text.'</a>';
}
}
}
Does somebody know how to insert the first 3 images of an order into the WooCommerce my-orders table?
Additionally I would like to add an "and more"-button, linked to the specific order (same link as order-number) with an if condition.
Hint: To stay more flexible it would be nice to get a solution without hooks, if possible.
I'd like to edit even more and overwrite the my-orders.php via child-theme later.
Here is the solution I use at the moment.
<div class="order-status">
<span>Order Status</span>
<?php
elseif ( 'order-status' === $column_id ) :
$order_color_check = $order->get_status();
if($order_color_check=="completed") :
echo '<span class="order-status-value" style="color: green;">' . esc_html( wc_get_order_status_name( $order->get_status() ) ) . '</span>';
else :
echo '<span class="order-status-value" style="color: red;">' . esc_html( wc_get_order_status_name( $order->get_status() ) ) . '</span>';
endif; ?>
</div>
Know that myaccount/my-orders.php is #deprecated since WC 2.6.0
My answer is via hooks, but editing via the template file should be done via myaccount/orders.php
The output of the html will need some CSS for styling (theme dependent)
// Adds a new column to the "My Orders" table in the account.
function filter_woocommerce_account_orders_columns( $columns ) {
// Add a new column
$new_column['order-products'] = __( 'Products', 'woocommerce' );
// Return new column as first
return $new_column + $columns;
}
add_filter( 'woocommerce_account_orders_columns', 'filter_woocommerce_account_orders_columns', 10, 1 );
// Adds data to the custom "order-products" column in "My Account > Orders"
function filter_woocommerce_my_account_my_orders_column_order( $order ) {
$count = 0;
// Loop through order items
foreach ( $order->get_items() as $item_key => $item ) {
// Count + 1
$count++;
// First 3
if ( $count <= 3 ) {
// The WC_Product object
$product = wc_get_product( $item['product_id'] );
// Instanceof
if ( $product instanceof WC_Product ) {
// Get image - thumbnail
$thumbnail = $product->get_image( array(50, 50) );
// Output
echo '<div class="product-thumbnail" style="display:inline-block;padding:2px;">' . $thumbnail . '</div>';
}
} elseif ( $count == 4 ) {
// Output "read more" button
echo '<span>'. __( 'Read more', 'woocommerce') . '</span>';
break;
}
}
}
add_action( 'woocommerce_my_account_my_orders_column_order-products', 'filter_woocommerce_my_account_my_orders_column_order', 10, 1 );
Does somebody know how to insert the first 3 images of an order into the WooCommerce my-orders table?
Additionally I would like to add an "and more"-button, linked to the specific order (same link as order-number) with an if condition.
Hint: To stay more flexible it would be nice to get a solution without hooks, if possible.
I'd like to edit even more and overwrite the my-orders.php via child-theme later.
Here is the solution I use at the moment.
<div class="order-status">
<span>Order Status</span>
<?php
elseif ( 'order-status' === $column_id ) :
$order_color_check = $order->get_status();
if($order_color_check=="completed") :
echo '<span class="order-status-value" style="color: green;">' . esc_html( wc_get_order_status_name( $order->get_status() ) ) . '</span>';
else :
echo '<span class="order-status-value" style="color: red;">' . esc_html( wc_get_order_status_name( $order->get_status() ) ) . '</span>';
endif; ?>
</div>
Know that myaccount/my-orders.php is #deprecated since WC 2.6.0
My answer is via hooks, but editing via the template file should be done via myaccount/orders.php
The output of the html will need some CSS for styling (theme dependent)
// Adds a new column to the "My Orders" table in the account.
function filter_woocommerce_account_orders_columns( $columns ) {
// Add a new column
$new_column['order-products'] = __( 'Products', 'woocommerce' );
// Return new column as first
return $new_column + $columns;
}
add_filter( 'woocommerce_account_orders_columns', 'filter_woocommerce_account_orders_columns', 10, 1 );
// Adds data to the custom "order-products" column in "My Account > Orders"
function filter_woocommerce_my_account_my_orders_column_order( $order ) {
$count = 0;
// Loop through order items
foreach ( $order->get_items() as $item_key => $item ) {
// Count + 1
$count++;
// First 3
if ( $count <= 3 ) {
// The WC_Product object
$product = wc_get_product( $item['product_id'] );
// Instanceof
if ( $product instanceof WC_Product ) {
// Get image - thumbnail
$thumbnail = $product->get_image( array(50, 50) );
// Output
echo '<div class="product-thumbnail" style="display:inline-block;padding:2px;">' . $thumbnail . '</div>';
}
} elseif ( $count == 4 ) {
// Output "read more" button
echo '<span>'. __( 'Read more', 'woocommerce') . '</span>';
break;
}
}
}
add_action( 'woocommerce_my_account_my_orders_column_order-products', 'filter_woocommerce_my_account_my_orders_column_order', 10, 1 );
I am trying to display the Woocommerce cart count by product category.
I have two categories: "protein" and "pantry"
I want to display the count by item category. So if there are 2 protein and 4 pantry, I want those two item category counts to be displayed next to each other, updating with ajax.
e.g. the final look would say: PROTEIN 2 in cart and PANTRY 4 in cart (depending on the amount of item types in the cart)
I have found this snippet here which displays the cart count for a given category, but I am having trouble displaying it on the web page correctly. Currently It just displays the total amount of items in the cart:
function cat_cart_count( $cat_name ) {
global $woocommerce; $cat_count = 0;
// For each product in the cart
foreach(WC()->cart->get_cart() as $cart_item_key => $values) {
$_product_id = $values['product_id']; // product ID
$_product_qty = $values['quantity']; // product quantity
// Getting categories of the product (could be more than one)
$terms = get_the_terms( $_product_id, 'product_cat' );
// Checking this product has a category
if ( $terms && ! is_wp_error( $terms ) ) {
$term_name = array();
// For each category of that product
foreach($terms as $term) {
// Adding the category name to an array
$term_name[] = $term->name;
// if the product has $cat_name category
if ( in_array( $cat_name, $term_name ) ) {
// add 1 x product quantity to the count
$cat_count =+ 1 * $_product_qty;
}
}
}
}
// Returning category count
if ( $cat_count != 0 ) {
return $cat_count;
} else {
return '';
}
}
I am trying to just display the counters as HTML so that I can embed on the page anywhere and customise from there:
<a class="cart-contents" href="<?php echo WC()->cart->get_cart_contents_count(); ?>" title="<?php _e( 'View your shopping cart' ); ?>"><?php echo sprintf (_n( '%d protein', '%d protein', cat_cart_count( "protein" ) ), cat_cart_count( "protein" ) ); ?> - <?php echo sprintf (_n( '%d pantry', '%d pantry', cat_cart_count( "pantry" ) ), cat_cart_count( "pantry" ) ); ?> - <?php echo WC()->cart->get_cart_contents_count(); ?></a>
Thanks in advance!
The main problem comes from the refreshed woocommerce ajax cart fragments that use by default "cart-contents" class and the existing content with the refreshed default cart count.
So we will need to:
rename that class differently,
add the content (to be refreshed on add to cart) in a specific hooked function.
I have also revisited, simplified and compacted your function cat_cart_count().
The complete code:
// Utility function that count specific product category cart items
function cat_cart_count( $term ) {
$count = 0; // Initializing
// Loop through cart items
foreach( WC()->cart->get_cart() as $cart_item ) {
if( has_term( $term, 'product_cat', $cart_item['product_id'] ) )
$count += $cart_item['quantity'];
}
// Returning category count
return $count == 0 ? false : $count;
}
// Utility function that displays the cart items counters
function display_cart_counters() {
ob_start();
$link = wc_get_cart_url();
$title = __( 'View your shopping cart', 'woocommerce' );
$count = __( '0 item', 'woocommerce');
// Displayed on first page load
echo '<a class="cart-contents-cat" href="' . $link . '" title="' . $title . '">' . $count . '</a>';
return ob_get_clean();
}
// Displaying refreshed content on add-to cart
add_filter( 'woocommerce_add_to_cart_fragments', 'counters_add_to_cart_fragment', 30, 1 );
function counters_add_to_cart_fragment( $fragments ) {
ob_start();
$term1 = 'protein';
$count1 = cat_cart_count( $term1 );
$output = $count1 ? sprintf ( __( '%d %s', 'woocommerce'), $count1, $term1 ) . ' - ' : '';
$term2 = 'pantry';
$count2 = cat_cart_count( $term2 );
$output .= $count2 ? sprintf ( __( '%d %s', 'woocommerce'), $count2, $term2 ) . ' - ' : '';
$count = WC()->cart->get_cart_contents_count();
$output .= $count ? sprintf (_n( '(%d item)', '(%d items)', $count ), $count ) : __( '0 item', 'woocommerce');
$link = wc_get_cart_url();
$title = __( 'View your shopping cart', 'woocommerce' );
// Replacement display on any cart item events
?>
<a class="cart-contents-cat" href="<?php echo $link; ?>" title="<?php echo $title ?>"><?php echo $output; ?></a>
<?php
$fragments['a.cart-contents-cat'] = ob_get_clean();
return $fragments;
}
Code goes in function.php file of your active child theme (or active theme).Tested and works.
USAGE
1) To place the counter in the html code of a php file you will use:
<?php echo display_cart_counters(); ?>
2) To use the counter inside any php code you will call the function **display_cart_counters()**.
I'm trying to display my product variation description in my Cart. I have tried inserting this code in the cart.php template:
if ( $_product->is_type( 'variation' ) ) {echo $_product->get_variation_description();}
By following this documentation https://docs.woocommerce.com/document/template-structure/
But it's still not showing up.
Not sure what I'm doing wrong here.
Can anyone help on this?
Updated for WooCommerce version 3 and above
Since WooCommerce 3, get_variation_description() is now deprecated and replaced by get_description() WC_Product method.
To get your product item variation description (filtering variation product type condition), you can use the following hooked function instead:
// Cart page (and mini cart)
add_filter( 'woocommerce_cart_item_name', 'cart_item_product_description', 20, 3);
function cart_item_product_description( $item_name, $cart_item, $cart_item_key ) {
if ( ! is_checkout() ) {
if( $cart_item['variation_id'] > 0 ) {
$description = $cart_item['data']->get_description(); // variation description
} else {
$description = $cart_item['data']->get_short_description(); // product short description (for others)
}
if ( ! empty($description) ) {
return $item_name . '<br><div class="description">
<strong>' . __( 'Description', 'woocommerce' ) . '</strong>: '. $description . '
</div>';
}
}
return $item_name;
}
// Checkout page
add_filter( 'woocommerce_checkout_cart_item_quantity', 'cart_item_checkout_product_description', 20, 3);
function cart_item_checkout_product_description( $item_quantity, $cart_item, $cart_item_key ) {
if( $cart_item['variation_id'] > 0 ) {
$description = $cart_item['data']->get_description(); // variation description
} else {
$description = $cart_item['data']->get_short_description(); // product short description (for others)
}
if ( ! empty($description) ) {
return $item_quantity . '<br><div class="description">
<strong>' . __( 'Description', 'woocommerce' ) . '</strong>: '. $description . '
</div>';
}
return $item_quantity;
}
Now the description is just displayed between the title and the variation attributes values (if there is any).
Code goes in functions.php file of the active child theme (or active theme). Tested and works.
This will work for WC 3.0
add_filter( 'woocommerce_cart_item_name', 'cart_variation_description', 20, 3);
function cart_variation_description( $title, $cart_item, $cart_item_key ) {
$item = $cart_item['data'];
if(!empty($item) && $item->is_type( 'variation' ) ) {
return $item->get_name();
} else
return $title;
}
You can get it via global variable $woocommerce also-
global $woocommerce;
$cart_data = $woocommerce->cart->get_cart();
foreach ($cart_data as $value) {
$_product = $value['data'];
if( $_product->is_type( 'variation' ) ){
echo $_product->id . '<br>';
}
}
I already check it.