5
votes

REVISED QUESTION: We have tracked this down to a custom add to cart method. I have completely revised the question.

I am working on a site that is using Magento ver. 1.3.2.4 as its eCommerce platform. We have built a custom "Add To Cart" process which adds multiple items to the cart via an AJAX request. After this request, some postprocessing is done viw JavaScript in the browser before redirecting to the "View Cart" page. 99% of the time this process seems to function properly in Firefox and Safari but in IE8, the process fails. When adding an item to the cart, after being redirected to the "Your Cart" page, the shopping cart is empty.

Not all items on the site are added via this AJAX process. This issue only happens only when the cart is empty before adding the items via AJAX. That is to say, if an item that is added via the normal Magento process is added to the cat first, then the AJAX add to cart requests always succeed. Blu clearing cookies and then attempting to add via AJAX will fail consistently on IE8.

Server is an Apache/PHP server with PHP 5.2.9, eAccelerator and Suhosin. Please request any additional information and I'll be happy to provide it. We are storing sessions in a MySQL Database.

Here is the code for our custom add to cart method. This code is located in /app/code/core/Mage/Checkout/controllers/CartController.php:

public function ajaxaddAction()
{
    $result = array('success' => true);

    try
    {
        $session = $this->_getSession();
        $cart = $this->_getCart();

        $products = json_decode($_POST['products'],true);

        if(!is_array($products))
        {
            throw new Exception("Products data not sent");
        }

        foreach ($products as $product_data)
        {
            $product = $this->_initProduct($product_data['id']);

            if(!$product)
                throw new Exception("Product id {$product_data['id']} not found");

            $info = array('qty' => $product_data['qty']);

            if($product_data['options'])
                $info['options'] = $product_data['options'];

            $cart->addProduct($product,$info);
        }

        $cart->save();

        $this->_getSession()->setCartWasUpdated(true);

        /**
         * @todo remove wishlist observer processAddToCart
         */
        Mage::dispatchEvent('checkout_cart_add_product_complete',
            array('product' => $products[0], 'request' => $this->getRequest(), 'response' => $this->getResponse())
        );

        $cartItems = $cart->getQuote()->getAllItems();

        $result['cart'] = array();

        foreach($cartItems as $item)
            $result['cart'][] = json_decode($item->toJson());
    }
    catch (Mage_Core_Exception $e)
    {
        if ($this->_getSession()->getUseNotice(true)) {
            $this->_getSession()->addNotice($e->getMessage());
        } else {
            $messages = array_unique(explode("\n", $e->getMessage()));
            foreach ($messages as $message) {
                $this->_getSession()->addError($message);
            }
        }
        $result['success'] = false;
        $result['exception'] = $e->getMessage();
    }

   catch (Exception $e) {
        $this->_getSession()->addException($e, $this->__('Can not add item to shopping cart'));
        $result['success'] = false;
        $result['exception'] = $e->getMessage();
    }

    header('Content-Type: application/json',true);

    ob_end_clean();

    echo json_encode($result);

    exit();
}

Please don't answer with "Move the code to the /app/code/local/ directory". I understand that's a better place for it, and will move it there in the future, but unless your answer will solve the issue, please just post a comment. In order to get a faster response I'm starting a bounty and want good answers to this specific issue, not just tips on better ways to integrate this code.

If there's any information I can provide to assist please let me know. We're under a tight deadline...

3
I lose my bounty even if I accept my own answer. And my own answer doesn't fully answer the question. Doesn't anyone want 550 rep points? ;-)Josh
@Josh, If you want half of your bounty back, just upvote it someone's answer, don't accept anything, if that answer get +2 upvotes, and if you don't accept anything, you and he will share bounty half/half when the bounty ends. stackoverflow.com/faqYOU
Shot in the dark: IE 8, unlike many other browsers, caches AJAX (only!) GET (only) responses by default. You have to add cache-control headers to the response to tell it not to. Use Fiddler to look very carefully at the traffic between IE and your site, and make sure that it's precisely what you expect.Craig Stuntz
Another shot in the dark: Race condition? Is it possible that for some reason the cart isn't updated yet when you serve the "View Cart" page?balpha
@Craig: I like your thinking -- you might be onto something! I'm going to run some tests now.Josh

3 Answers

4
votes

I've spent over 10 hours on this. For the moment I believe I have a partial solution. But I'm not sure why this solution works...

It seems that Magento requires a redirect in order to complete the add to cart process. So instead of

header('Content-Type: application/json',true);
ob_end_clean();
echo json_encode($result);
exit();

I store my JSON in the session and redirect to a new cart action:

$this->_getSession()->setCartJsonResult(json_encode($result));
$this->_redirect('checkout/cart/postajaxadd');

That action then dumps the JSON data

public function postajaxaddAction()
{
    $session = $this->_getSession();

    header('Content-Type: application/json',true);
    ob_end_clean();
    echo $this->_getSession()->getCartJsonResult();
    exit();
}

This still fails sometimes; however now my JavaScript code does not get the JSON data it was expecting and is able to repeat the request. The second request is successful more often than the first... However there are still cases when the AJAX requests fail no matter what.

3
votes

Not sure if this is causing the problems you're running into, but a better way to do a JSON response would be to use the existing "Magento/Zend way" of doing it.

Instead of:

header('Content-Type: application/json',true);

ob_end_clean();

echo json_encode($result);

exit();

Use:

$this->getResponse()->setHeader('Content-Type', 'application/json', true)->setBody(json_encode($result));
1
votes

We've experienced issues adding things to the cart when session storage runs out and new sessions can't be created. If you're storing sessions on disk or in memcache, check that you've allocated enough space.