Is there a global way to check in any .tpl file without making modifications to the controllers and views to see if the basket is empty. This does not always work:
$cartItems = $this->cart->countProducts();
if ($cartItems < 0) {
print "Your cart is empty"
}
It appears that it works when logged in and sometimes as a guest?
Much better sollution is just to call
if ( ! $this->cart->hasProducts()) {
print "Your cart is empty";
}
It is much quicker and refers directly to a product count within a cart.
The method $this->cart->countProducts() does not count the products within a cart, but calculates the total product pieces count within a cart. So it loads all the products in a cart and in a loop adds each product's quantity. Therefore it is slower - not much, You might even not register the difference - but yet it is a little slower (the more products in a cart the more slower it is because of the loop).
$cart_contents = $this->cart->countProducts();
if ($cart_contents === 0) {
print "Your cart is empty"
}
Related
I am currently trying to make an if else check in the checkout of a WooCommerce site.
I need to know if the total is greater or less than 100, so that it will say "You need to call to negotiate a shipping fee".
The code:
$woocommerce->cart->get_cart_total()
shows the value, but adds HTML content.
I need only the value itself.
I kind of found out how to do this the hard way.
I searched google for over 2 hours and found this page: https://woocommerce.wp-a2z.org/oik_api/wc_cartget_cart_subtotal/
global $woocommerce;
$subtotal = $woocommerce->cart->get_subtotal();
$subtax = $woocommerce->cart->get_subtotal_tax();
$subtotaltax = $subtotal+$subtax;
echo with $subtotaltax shows the value with the tax added.
In Woocommerce, I would like my customers to buy either 18 or 36 products but not between the two. I wanna remove the possibility to checkout from 19 to 35.
You told me in comment that you don't know php well. Most of the time we don't offer php code here, but I found it interesting to do. And it may helps some people in the future.
As I said, one possibility is to do a redirection to the cart page on the checkout page if the customer doesn't have 18 or 36 products. After the redirection on the cart page, you must display a message for the customer to see that he must have 18 or 36 products.
Summary
add_action on template_redirect to check the product count and handle the redirection. If we it redirects, add an arg like invalid-cart-product-count in the url with value equal to the product count.
add_action on woocommerce_before_cart to check if we get the invalid-cart-product-count so we display a message.
Working code (tested)
There is the code that you need to place in your functions.php file of you theme or child theme (preferred option).
/**
* Check on template redirect the cart product count
*/
add_action('template_redirect','product_count_template_redirect');
function product_count_template_redirect() {
// If we are on checkout and the cart contents count is not equal to 18 or 36
if(is_checkout() && !in_array(WC()->cart->get_cart_contents_count(), array(18, 36))) {
// Redirect on the cart page and add a query arg to the url so we can check for it and add a message
wp_redirect(esc_url(add_query_arg('invalid-cart-product-count', WC()->cart->get_cart_contents_count(), wc_get_cart_url())));
exit;
}
}
/**
* Handle the message on the cart page if we have the 'invalid-cart-product-count' arg in url
*/
add_action('woocommerce_before_cart', 'cart_page_message');
function cart_page_message() {
// If its set and not empty
if(!empty($_GET['invalid-cart-product-count'])) {
// Display the message with the current cart count and the count that user need to have
$message = "<div class='woocommerce-error'>";
$message .= sprintf(
__('You currently have <strong>%s</strong> products in your cart. You must have <strong>18</strong> or <strong>36</strong> products in your cart to be able to checkout', 'your-text-domain'),
// Force the arg to be an int, if someone malicious change it to anything else
(int) $_GET['invalid-cart-product-count']
);
$message .= "</div>";
echo $message;
}
}
Tell me if you don't understand or if this not exactly what you need.
I have my woocommerce page to sell a single product. I need to to go to the cart page with default value of 1 in cart page, so that when users click
www.test.com/cart
it never says "cart is Empty"!
Any ways to do that?
What do I need to do? Any ideas?
It sounds like you want to add a product to the user's cart even if they haven't actually added it themselves:
So that when users click www.test.com/cart it never says "cart is Empty"
For what it's worth, I don't think that's a fantastic idea from a UX point of view (or pretty much any other). However, it is possible.
Be warned: This code is largely untested, and it's triggered to run on init (although it should only run each time the cart is visited). Generally, I would advise against this - but it should do what you want:
function vnm_addThingToCart() {
// Check we're not in admin
if (!is_admin()) {
// Only do this on the cart page
if (is_page('cart')) {
global $woocommerce;
// You're only selling a single product, so let's make sure we're not going to add the same thing over and over
$myProductID = 22; // Or whatever
$productToAdd = get_product($myProductID);
// Make sure the product exists
if ($productToAdd) {
// Make sure there's stock available
$currentStock = $productToAdd->get_stock_quantity();
if ($currentStock > 0) {
// Add the product
$woocommerce->cart->add_to_cart($myProductID);
}
}
}
}
}
add_action('init', 'vnm_addThingToCart');
I have a tiny problem with adding products into global array. This may be used in shop cart. Here is the part of code that we focus in:
if ( isset($_POST['id']) ){ // If the product is adding to cart. This product Id is sended via form.
$productid = mysql_real_escape_string($_POST['id']);
$cartproduct = mysql_query("select * from stuff where id = '$productid'");
$Addrow=mysql_fetch_assoc($cartproduct);
if ($Addrow['qty']<$_POST['qty']){ // the product quantity that will add to cart can't be greater than in database
$_POST['qty']=$Addrow['qty'];
}
$new_product = array(array('name'=>$Addrow['name'], 'id'=>$Addrow['id'], 'price'=>$Addrow['price'], 'qty'=>$_POST['qty'])); // Creating new product info in array
if (isset($_SESSION['cart'])){ // If the cart exist
foreach ($_SESSION['cart'] as $add_product){
if ($add_product['id']==$_POST['id']){ // checking that product is already in $_SESSION
$exist = TRUE;
}else{
$exist = FALSE;
}
}
if ($exist == TRUE){ // If The product is in the $_SESSION: Update amount
// I dont have code for it.
}else{ // The product is not in array, add it.
$_SESSION["cart"] = array_merge($_SESSION["cart"], $new_product);
}
}else{ // If the cart is not exist
$_SESSION['cart']=$new_product;
}
}
And the problem is when I try to add the product that already in array. The function is adding it as new product...
The second problem is with remove these products. I can't do this using this:
foreach ($_SESSION['cart'] as $remove){
if($_GET["id"] == $remove['id']){
unset($_SESSION["cart"][$remove]);
}
}
Anyone can help to solve it?
I would suggest to change the array a bit. Inside 'cart', use the product id as a key for the products. That way, you can easily find and update products in the array.
You can just change the cart array in the session. Because keys are unique in the array, setting a value for the key will overwrite the previous one.
So I've added a slightly modified version of your inner piece of code. It performs three steps:
Add the post variables to normal variables. I find this easier to work with, and you can do all kinds of other checks before continuing (like checking if quantity > 0 etc).
Get the existing product from the array or initialize a new product. This uses array_key_exists, because I think that's the purest check, but people also use isset($_SESSION['cart'][$productId]), which should also work. Anyway, such a check is better (faster, easier) than using a loop, but it will only work if you switch to using product ids for the keys.
Simply set or update the quantity and write the updated prodct back into the array. If the product existed before, it will just overwrite the previous value.
Code becomes:
// Use a variable. It's easier and more readable.
$productId = $_POST['id'];
$quantity = $_POST['qty'];
// Your other checks go here. Left out for brevity.
// Get the current product from the cart, if it exists.
// If not, create a new product.
if (array_key_exists($productId, $_SESSION['cart'])) {
// Product found, get it and update its quantity.
$product = $_SESSION['cart'][$productId];
$product['qty'] += $quantity;
} else {
// Product not found. Initialize a new one.
$product = array(
'name' => $Addrow['name'],
'id' => $Addrow['id'],
'price' => $Addrow['price'],
'qty' => $quantity);
}
// Write updated or new product back to the array, and use the product id as key.
$_SESSION['cart'][$productId] = $product;
Some other tips:
Don't use the mysql_* functions if you have the opportunity to switch to mysqli or PDO. The mysql functions are deprecated.
Make sure to check the query result. Maybe something went wrong (or someone forged a request), and the product id cannot be found in the database. In that case, $Addrow will probably be false or null. Make sure to check for this and display an appropriate error instead of updating cart, possibly corrupting your cart.
If the quantity cannot be added, I wouldn't silently lower the quantity, because the user will think they found a bug. Instead, clearly state that such a quantity is not available.
And you may want to reconsider that. After all, maybe other stock will be delivered today, or other people might order the last item simultaneously. So it's better to check it later, when the order is well saved and you want to process it.
Showing information about available quantities in the cart will give your competition insight in the amount of stock you have, from which they can deduce other information too. Also, they may even place fake orders to make products unavailable on your website. It's a dog-eat-dog world. Be careful what information you show.
I am using Magento 1.7.0.2. Whilst on the product page, if a customer attempts to add a quantity greater than we have in stock they receive a message stating ".. the requested quantity is not available".
Is there any way for magento to either email or log when this occurs? I.e. I receive an automatic email stating a customer has attempted to add X number of item X? This would allow me to identify lost sales due to us not having enough stock of a particular item?
Has anyone come across anything like this before or is this even possible?
Thank you in advance
Mike Prentice
yes this is possible
You have to code for this.
I came across this problem one time and what i have do like this below.
I have make one observer event to check if customer is requesting quantity more then available if so i sent email to admin.
What you can do is create one observer for chekout_cart_add_before event in this event you can put your logic.
Or otherwise you can use magento feature Backorders you can find this in inventory tab,if you enable this then customer can order even requested quantity > available quantity, customer can see one message in cart page about backorder.
There is no standart functionality to notify about low quantity products by email.
But there is RSS notification http://www.magentocommerce.com/wiki/modules_reference/english/mage_adminhtml/system_config/edit/cataloginventory
Extend this functionality to match your needs.
You could write some script which would parse RSS, and send email etc.
EDIT
Here is some extension you may like http://www.magentocommerce.com/magento-connect/low-stock-email-notification.html
But is is not free.
Here's how I've done it so that it sends a google analytics tracking event whenever a customer tries to order more than the available stock level.
First copy: app/code/core/Mage/CatalogInventory/Model/Stock/Item.php
To: app/code/local/Mage/CatalogInventory/Model/Stock/Item.php
so that you're not modifying a core file.
In app/code/local/Mage/CatalogInventory/Model/Stock/Item.php add this function
public function notifyOutOfStock($productId){
$session = Mage::getSingleton('checkout/session');
//Initialise as empty array, or use existing session data
$outOfStockItems = array();
if ($session->getOutOfStock()){
$outOfStockItems = $session->getOutOfStock();
}
try {
$product = Mage::getModel('catalog/product')->load($productId);
$sku = $product->getSKu();
if($sku){
//Add the current sku to our out of stock items (if not already there)
if(! isset($outOfStockItems[$sku]) ) {
$outOfStockItems[$sku] = 0;
}
}
} catch (Exception $e){
//Log your error
}
Mage::getSingleton('checkout/session')->setOutOfStock($outOfStockItems);
}
In that same file is another function called checkQuoteItemQty.
Inside that function you need to call your new function using $this->notifyOutOfStock($this->getProductId()); right after it sets each of the error messages and before the return statement.
So:
public function checkQuoteItemQty($qty, $summaryQty, $origQty = 0)
{
....
if ($this->getMinSaleQty() && ($qty) < $this->getMinSaleQty()) {
$result->setHasError(true)
->setMessage(
$_helper->__('The minimum quantity allowed for purchase is %s.', $this->getMinSaleQty() * 1)
)
->setQuoteMessage($_helper->__('Some of the products cannot be ordered in requested quantity.'))
->setQuoteMessageIndex('qty');
//** Call to new function **
$this->notifyOutOfStock($this->getProductId());
return $result;
}
.....
->setQuoteMessageIndex('qty');
//** Call to new function **
$this->notifyOutOfStock($this->getProductId());
return $result;
.....
What this does is add your product sku to an array in the checkout session.
This means you will have access to that info in the template file right after your page loads displaying the "Insufficient stock" notification.
So in one of your template files you can add some code to render the necessary JavaScript.
I've chosen header.phtml since it loads on every page. (Users can add quantities of items to the cart in the cart page as well as the product view page).
app/design/frontend/CUSTOMNAME/default/template/page/html/header.phtml
Somewhere down the bottom of the code add this:
<!-- GA tracking for out of stock items -->
<script>
try {
<?php
$session = Mage::getSingleton('checkout/session');
if ($session->getOutOfStock()){
$outOfStockItems = $session->getOutOfStock();
foreach($outOfStockItems as $sku=>$value) {
if($value==0){
//Render the GA tracking code
echo "_gaq.push(['_trackEvent', 'AddToCart', 'ProductQtyNotAvailable', '".$sku."']); \r\n";
//Set it to 1 so we know not to track it again this session
$outOfStockItems[$sku] = 1;
}
}
//Update the main session
Mage::getSingleton('checkout/session')->setOutOfStock($outOfStockItems);
}
?>
}
catch(err) {
//console.log(err.message);
}
</script>
Can confirm this works well and in my opinion is better than an email or RSS feed as you can analyse it along with the rest of your analytics.