I need to create a possibility for customers to offer a one product free of charge (as an example) in Magento shop. I figured out most of things from this post, but now I have one problem. I am created an Observer method that is executed on checkout_cart_product_add_after. And there I have some code (its just a part of whole thing):
$productId = $observer->getProduct()->getId();
$cartHelper = Mage::helper('checkout/cart');
$items = $cartHelper->getCart()->getItems();
Mage::getModel('core/session')->addNotice('Product id: '.$productId);
foreach ($items as $item) {
if ($item->getProduct()->getId() == $productId) {
$itemId = $item->getItemId();
$cart = $cartHelper->getCart()->removeItem($itemId)->save() ;//It WORKS!!!!!!!!!!!!
$product = Mage::getModel('catalog/product')->load($productId);
$cart->addProduct($product, $this->_getRequest()->getParams());
$cart->save();
Mage::getSingleton('checkout/session')->setCartWasUpdated(true);
break;
}
}
So first of all my code adds a product to cart with 0.00 price (product as an example) based on some request parameters. Thats part works fine so it is not posted here. The second part (that I posted above) must delete an existing product and replace it with product with normal price. Almost everything works fine except one thing - the line $cart->addProduct($product, $this->_getRequest()->getParams()); don't work and I cant understand why (no errors, no exceptions, no logs).
_getRequest method looks like this:
protected function _getRequest()
{
return Mage::app()->getRequest();
}
And if I log an $this->_getRequest()->getParams() there is will be something like this:
2012-04-09T14:46:56+00:00 DEBUG (7): Array(
[uenc] => aHR0cDovL2xvY2FsaG9zdC93b3AvZmVhdHVyZWQvY2xhc3NpYy1saW5lLXBvbHkuaHRtbA,,
[product] => 50
[related_product] =>
[bundle_option] => Array(
[20] => 75
[21] => 84
[22] => 94
)
[qty] => 1
[send-request] => 0
)
So why that $cart->addProduct($product, $this->_getRequest()->getParams()); will not work? How to do it right? Maybe it is better to use addAction() of Mage_Checkout_CartController (overwrite it)?
Sorry for my language. Thanks for answers. Hope somebody can help me...
I'll answer my question to clarify things for anybody, who will stumble the same problem.
The code:
$cart->addProduct($product, $this->_getRequest()->getParams());
will not work because I call $cart->save() before it and than tried to do the same after it and that was the problem. When I removed first $cart->save() it is worked just fine.
Related
I have the following issue:
I make calculations via jQuery in the frontend and want to add a product to the cart with the price calculated in the frontend.
I already wrote a custom module with an AjaxController to achieve the adding to cart part, but I know struggle with setting the custom price.
My script looks like this:
$_prod = json_decode(Mage::app()->getRequest()->getPost('zapfsaeule_product'));
$id = 347; // there is only this one bundle product added to the cart viar this scipt, so a static id is enough.
$params = array(
'product' => $id,
'related_product' => null,
'bundle_option' => array(
6 => 17, // static options for testing purpouses
5 => 13), //
'qty' => 1 // static qty for testing as well
);
$cart = Mage::getSingleton('checkout/cart');
$product = new Mage_Catalog_Model_Product();
$product->load($id);
$cart->addProduct($product, $params);
$cart->save();
Mage::getSingleton('checkout/session')->setCartWasUpdated(true);
$this->getResponse()->setBody('true'); // setting response to true, because its an ajax request.
$this->getResponse()->setHeader('Content-type', 'text/plain');
That's the code for adding the product.
For setting the price I tried the approach as mentioned in this thread on stackexchange:
https://magento.stackexchange.com/questions/4318/dynamically-calculated-prices-save-before-add-to-cart
But it didn't work. I guess the event observed here doesn't occur in my case, because I wrote a custom script.
But then there still would be the problem, IF the observer approach would work, how would I pass the calculated price to the observer?
I hope you understand the problem and can help me solve it.
Thanks in advance!
Best regards,
Martin
Reading through Mage_Checkout_Model_Cart::addProduct(), there doesn't appear to be a way to set the item's price from the parameters. Instead, you'll need to add the product, then grab the resulting item, and set its price:
$cart->addProduct($product, $params)
->save();
// grab the corresponding item
$item = $cart->getQuote()->getItemByProduct($product);
// set its custom price
$item->setOriginalCustomPrice($customPrice)
->save();
Haven't had the time to try this out, but it should be the right idea. Make sure that you set the original_custom_price field (using setOriginalCustomPrice()), not one of the other prices. The other prices are recalculated during the totals process.
This comes pretty late, but I just stumbled upon this.
I got it to work like this:
$cart = Mage::getSingleton('checkout/cart');
$cart->addProduct($product, 1); // 1 = qty. Pass your qty and params.
$item = $cart->getQuote()->getItemByProduct($product);
$item->setCustomPrice(0); // or some other value
$item->setOriginalCustomPrice(0); // or some other value
$item->getProduct()->setIsSuperMode(true); // this is crucial
$cart->save();
Mage::getSingleton('checkout/session')->setCartWasUpdated(true);
If the params don't work, fetch the returned item from $cart->addProduct and change the price on the item before saving the cart.
$item = $cart->addProduct(...);
$item->setCustomPrice(...); {or whatever price attribute you like to set}
$cart->save();
I have test php script running outside of Magento that will add an item to the cart. Works great. This code was found here and used by many people in quite a few posts. When I place this code into an existing module, the item is not added, from a fresh session. If I go to the store and add a regular product (have an item in my cart) the module will add the item properly. I Know the code to add the item works. The problem I have is with creating the FIRST instance of a cart.
This code works just fine if already have a normal magento product in my cart:
// this section of code only works if the customer already has a cart item added (cart established)
// for some reason this script fails when no cart exists
$session = Mage::getSingleton('customer/session');
// Get cart instance
$cart = Mage::getSingleton('checkout/cart');
$cart->init();
$productId=971;
$productInstance = Mage::getModel('catalog/product')->load($productId);
$param = array(
'product' => $productId,
'qty' => $rfqdata['option_quantity'],
'options' => array(
27 => $rfqdata['option_layers'], // Layers
26 => $rfqdata['option_thickness'], // Thickness
25 => $rfqdata['option_length'], // Length
24 => $rfqdata['option_width'], // Width
23 => $rfqdata['option_color'], // Color
22 => $rfqdata['option_finish'], // Finish
29 => $rfqdata['option_rush'], // Rush
30 => 'tbd' // RFQ Number
)
);
$request = new Varien_Object();
$request->setData($param);
$cart->addProduct($productInstance, $param);
$session->setCartWasUpdated(true);
$cart->save();
This somehow causes an error, and the module addtocart action is not completed. I cannot find any useful error messages. I have searched 100s of pages on stack, google, and I can find nothing to resolve this issue. Obviously my module is worthless if it doesn't work from page load 1.
I tried to post this before and got no response. I really need some help. If you cannot answer, can you tell me where I can find paid Magento support?
here is the solution, it was very hard to find too....
if(empty($quote)){
$checkout = Mage::getSingleton('checkout/session');
$quote = $checkout->getQuote();
$session = Mage::getSingleton('customer/session');
if($session->isLoggedIn()) {
// look up customer
$customerSession = $session->getCustomer();
$customer = Mage::getModel('customer/customer')->load($customerSession->getId());
$quote->assignCustomer($customer);
$quote->setIsMultiShipping(false);
}
$quote->save();
}
Yesterday I posted a question on SO HERE regarding a multidimensional $_SESSION array I was working with to keep track of items in a shopping cart I'm developing. One of the very helpful responses suggested I create the $_SESSION array not as a multidimensional array, which I agree is a smoother approach.
The $_SESSION array is started when a user clicks any of the 'Add to Cart' buttons on the store page. My original code with the multidimensional array is this:
$quantity = 1;
// add first item from shop page
if(isset($_POST['add_item']) && (!isset($_SESSION['cart']))) {
$_SESSION['cart'] = array();
$_SESSION['cart'][$_POST['product_description']] = array('quantity' => $quantity, 'price' => $_POST['product_price']);
header("Location: http://website.com/cart.php");
}
And this worked fine, but I was not able to achieve the results with this that I wanted (see the other post).
The code I was suggested to use is this:
$quantity = 1;
// add first item from shop page
if(isset($_POST['add_item']) && (!isset($_SESSION['cart']))) {
$_SESSION['cart'][] = array('product_description'=> $_POST['product_description'], 'quantity' => $quantity, 'price' => $_POST['product_price']);
header("Location: http://website.com/cart.php");
}
And it works great and allows me to do what I want to do (again, see the other post for details).
HOWEVER...
Regardless of which 'Add to Cart' button is clicked on the store page (there are only four), the FIRST click gets information added to the $_SESSION['cart'] array TWICE. Every other button clicked afterward is entered only once. And again, it does not matter which button is clicked first, this happens no matter what.
Here's the result of a print_r on the new $_SESSION array code:
Array
(
[0] => Array
(
[product_description] => iPhone case - Black
[quantity] => 1
[price] => 9.49
)
[1] => Array
(
[product_description] => iPhone case - Black
[quantity] => 1
[price] => 9.49
)
)
I have scoured SO and Google for clues as to why this is happening, but no matter how I word my queries, I just can't seem to find anything that helps.
It has to be something simple that I am missing...
Sincere thanks in advance!
UPDATE
To clarify, there are only 4 items on the store page. There won't ever be any more. To keep things super simple, each item has its own 'Add to Cart' button. When the button is clicked, the user is taken to the cart page where they can adjust the quantity or delete the item then either check out cancel and clear the cart or continue shopping.
Your description seems to say you want something like:
check to see the cart exists, create if it doesn't
then add the item to the cart
The code you posted seems to only add an item, if you don't have a cart yet.
The only reason I can think of for the double item though is that there is more code than you posted and you have the code for the "add item" bit happening in both the "create cart" and a later "add item" chunk.
Here's what I would do:
quantity = 1;
// ensure cart
if (!isset($_SESSION['cart'])) {
$_SESSION['cart'] = array();
}
// add item from shop page
if(isset($_POST['add_item'])) {
$_SESSION['cart'][$_POST['product_description']] = array(
'quantity' => $quantity,
'price' => $_POST['product_price']
);
// or if you prefer the numeric indexed array:
// $_SESSION['cart'][] = array(
// 'product_description'=> $_POST['product_description'],
// 'quantity' => $quantity,
// 'price' => $_POST['product_price']);
header("Location: http://website.com/cart.php");
}
I've modified your code in place to keep the logic simple, but like #dognose comments: do not trust the prices passed via the post. It is far to simple to hack a form and post you bad data to get your stuff for $0.01 like that.
Cannot answer as the full code is not provided; However:
$_SESSION = array_map("unserialize", array_unique(array_map("serialize", $_SESSION)));
will remove the duplicates from your session.
I am creating a new cart addAction() in magento's checkout/controllers/cartController.php. My need is, Whenever a product is added to cart, all existing products in cart should be cleared except currently added one. That is,
If Nokia 3220 is added to an empty cart, It should be placed as an item.
And Later if Nokia N72 is added, Nokia 3220(ie the previous item) should be cleared from cart and Nokia N72 should be placed and so on.
I override the CartController.php and added the code to begining of addAction() in CartController.php,
$checkout_my_cart = Mage::getSingleton('checkout/cart');
$current_items = $checkout_my_cart->getItems();
foreach ($current_items as $item)
{
$itemId = $item->getItemId();
$checkout_my_cart->removeItem($itemId)->save();
}
But It clears the entire cart when I add a new item to replace existing one! I think It should not do it since I added the code in the begining of Addaction(). I tried by defining the above code as a function and calling it with addAction(). But story seems to be the same.
Any help will be appreciated.
Please Help.
You should consider using observer rather then overriding controller. If you look at the addItem method within Mage_Sales_Model_Quote you will find that event sales_quote_add_item.
You can observe it, fetch the quote_item (argument to event) and delete items other then this one (was typing by hand so please double check for errors):
public function observeAddItem($observer)
{
$item = $observer->getEvent()->getQuoteItem();
$cart = Mage::getSingleton('checkout/cart');
foreach ($cart->getQuote()->getItemsCollection() as $_item) {
if($_item->getId() != $item->getId()) {
$_item->isDeleted(true);
}
}
}
Overriding classes (especially controllers) should be your last resort.
More info on how to observe event can be found on magento wiki:
http://www.magentocommerce.com/wiki/5_-_modules_and_development/0_-_module_development_in_magento/customizing_magento_using_event-observer_method
Hi please check below code:
$session= Mage::getSingleton('checkout/session');
$quote = $session->getQuote();
$cart = Mage::getModel('checkout/cart');
$cartItems = $cart->getItems();
foreach ($cartItems as $item){
$quote->removeItem($item->getId())->save();
}
I searched around for a while and only came up wit solutions that added whole new option sets to products in a Magento store.
What I'm trying to accomplish is a way to add a Simple Product to the cart. This Simple Product has some predifined custom options (free text fields) that has to be filled by a php function.
So, how can I do this? Let's say I have a product with the ID "111" and a one custom option.
$qty = '1';
$product = Mage::getModel('catalog/product')->load("111");
// set option value in product model?
$cart = Mage::helper('checkout/cart')->getCart();
$cart->addProduct($product, $qty);
// set option value while passing product to car?
$cart->save();
Thanks in advance for any hinds.
BTW: setting option values via QueryString is relativly easy as seen here.
You don't set the custom option on the product model, you pass it in through the second argument to $cart->addProduct($product, $params).
The set up we have for a project, that requires an external app to add to the Magento cart, is to use a $params array of the following format:
$params = array(
'product' => 1, // This would be $product->getId()
'qty' => 1,
'options' => array(
34 => "value",
35 => "other value",
53 => "some other value"
)
);
The $params['options'] contains the custom option information. The keys are the custom option ids, you can see them if you inspect the custom options section of the product screen with Firebug, or similar.
The $params['product'] may be redundant, I wrote this script a while ago for a much earlier version of Magento.
Also, I'm fairly sure that the standard add to cart events will fire when you add this way, so you'll need to set them off yourself. There may be side effects.
In Magento 1.7 you have to wrap the params array in a Varien Object.
$params = array(
'product' => $_fancypack->getId(),
'qty' => 1,
'options' => array(
$this->_getOptionId($_fancypack,'Product SKU') => $product->getId() .'/'. $product->getSku()
)
);
$request = new Varien_Object();
$request->setData($params);
$quote->addProduct($_fancypack, $request);
You should write the input parameter for addproduct as the following format, it is tested by myself:
$params = array(
'product' => 1, // This would be $product->getId()
'qty' => 1,
'super_attribute' => array(
34 => "value",
35 => "other value",
53 => "some other value"
)
);
The problem with the current answer is that magento will not add a second line item if the SKU is the same but the options are distinct from the first. If you want a 3" apple and a 4" apple you would like to have separate line items. Or at least I do.
A HTTP call to the following URL
/store/checkout/cart/add?product=23&qty=1&options[41]=4
followed by
/store/checkout/cart/add?product=23&qty=1&options[41]=3
will add two line items.
But still this is just half of the battle, what do these option codes stand for?? Well the following PHP code will tell you. And since we are using an HTTP call the code will return javascript ready JSON.
<?php
include_once '../app/Mage.php';
Mage::app();
echo getProductOptionsIds($_GET['eventcode']);
function getProductOptionsIds($sku)
{
$ProductID = Mage::getModel('catalog/product')->getIdBySku($sku);
$Product = Mage::getModel('catalog/product')->load($ProductID);
$config = array();
$config['ProductID'] = $ProductID;
foreach ($Product->getOptions() as $option) {
// #var $option Mage_Catalog_Model_Product_Option
if ($option->getGroupByType() == Mage_Catalog_Model_Product_Option::OPTION_GROUP_SELECT) {
$_tmpValues = array();
foreach ($option->getValues() as $value) {
// #var $value Mage_Catalog_Model_Product_Option_Value
$_tmpValues[$value->getTitle()] = $value->getId();
}
$config[$option->getTitle().'list'] = $option->getId();
$optionValue = $_tmpValues;
} else {
$optionValue = $option->getId();
}
$config[$option->getTitle()] = $optionValue;
}
return json_encode($config);
}
?>