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');
Related
I am a WP noob but very comfortable in PHP.
I am working with a client and we have built a product customization tool as an Angular.js single page application. When the product is finished being customized we are seeking to inject it into a WooCommerce cart so the client can check out. To do this we are $_POSTing the data to a PHP file in the root directory of the WP install. The code to catch it looks like:
require_once('./wp-load.php' );
global $woocommerce;
$woocommerce->session->set_customer_session_cookie(true);
$woocommerce->cart->empty_cart();
$id_arr = $_GET['productID'];
$pdfName = $_GET['pdfName'];
for($i=0; $i<count($id_arr); $i++){
$id = $id_arr[$i];
if ($id==0) continue;
if ($i==0){
$ret = $woocommerce->cart->add_to_cart($id, 1, '', '', array('pdfName'=>$pdfName));
}else{
$ret = $woocommerce->cart->add_to_cart($id);
}
}
wp_redirect(site_url().'/cart/');
The products are all correctly added to the cart but after checkout there is no sign of the metadata. After extensive research, I have found an article here: https://wpml.org/forums/topic/woocommerce-add-to-cart-does-not-work-with-wpml-activated/ that shows me that plugins can cause this behavior. So I have two specific questions?
Does my code make sense, am I creating the metadata array correctly?
Do I need to create something in WooCommerce called pdfName before I can do this?
Is there another way that metadata can be added to an order in
WooCommerce that may work around this problem?
It looks like you are adding the metadata correctly. However, as soon as you refresh, WooCommerce re-creates the cart data. Therefore you have to tell WooCommerce to maintain the metadata when it is pulling the cart from the stored session. Well, at least that is my understanding of it. So I think you need to filter thee $cart_item as it is run through the woocommerce_get_cart_item_from_session filter:
add_filter( 'woocommerce_get_cart_item_from_session', 'so_29660316_get_cart_item_from_session', 11, 2 );
function so_29660316_get_cart_item_from_session( $cart_item, $values ) {
if ( isset( $values['pdfName'] ) ) {
$cart_item['pdfName'] = $values['pdfName'];
}
return $cart_item;
}
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 have Magento multi-store websites that I want that the user will be able to add products to his shopping cart from all the website and pay once.
I successfully done it using this article.
But when the user click on the product in the shopping cart, he is not redirected to the right website. It's a limitation the described in the article at the end.
The link for editing items in the cart will redirect customer to
original cart website. It is possible to change it, you can override
getUrl method for cart items block or override controller.
I couldn't find any explaination to how to do this override.
Someone can help me do this?
Thanks
In my case i seen file of cart's item.phtml, it was using getproducturl().
So, I modified that method in file /app/code/core/Mage/Checkout/Block/Cart/Item/Renderer.php line 152.
I made condition that if its main website don't change otherwise it adds stores code in url like www.example/store1/Producturl.
I hope This will Help You.
As You Require The File method. Check belowed code.
public function getProductUrl()
{
if (!is_null($this->_productUrl)) {
return $this->_productUrl;
}
if ($this->getItem()->getRedirectUrl()) {
return $this->getItem()->getRedirectUrl();
}
$product = $this->getProduct();
$option = $this->getItem()->getOptionByCode('product_type');
if ($option) {
$product = $option->getProduct();
}
$webids = $product->getWebsiteIds();
$wid = array();
foreach($webids as $webid){
$wid[] = $webid;
}
if(!in_array(1,$wid)){
$website = Mage::app()->getWebsite($wid[0])->getCode();
$org_url = $product->getUrlModel()->getUrl($product);
$mod_url = str_replace("www.example.com/index.php/","www.example.com/".$website."/index.php/",$org_url);
return $mod_url;
}
return $product->getUrlModel()->getUrl($product);
}
As my first website id was "1", that's why i used in_array(1.$wid). You Can use your main website id over there. and in str_replace u can use baseurl() method of main website instead of static value i used.
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.
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"
}