views:

1984

answers:

3

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...

+1  A: 

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.

Chris Norton
Thanks for the advice. That is a good point. I am storing sessions in the database, and space is fine.
Josh
+3  A: 

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 excepting 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.

Josh
How about setting `text/plain` instead of `application/json`, I think some browser don't know that content-type.
S.Mark
I am using Prototype and it expects application/json... Also, this has no effect on whether the item gets added to the cart. Thanks though!
Josh
+2  A: 

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));
Chris Norton
Nice. That didn't solve the issue but it's a better way of handling it than my way. Thanks a lot!
Josh
I implemented that code -- it's much clearer, but the issue still exists.
Josh

related questions