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...
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.
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));
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.
Related
I trying to make my prestashop site faster. My question is: is there a way to get all products pages cached AT ONCE. I already enabled the cache. But if you visit a page for the first time it take too much time to load. Then, the second visit is much faster.
I don't see any feature in the admin page to get this.
Thanks.
There is no but you can create a script which will load every product pages on your website.
Put this script at the root of your Prestashop installation /test.php. and call it from your browser www.mywebsite.com/test.php:
<?php
// The script will not timeout for 10 hours
set_time_limit(36000);
// Set the right path to config.inc.php
include_once (__DIR__ . '/config/config.inc.php');
// Set a default controller to remove unwanted warnings.
$context = Context::getContext();
$context->controller = new FrontController();
// Get all products
$products = Product::getProducts(1, 0, 1000000, 'id_product', 'DESC', false, true, $context);
foreach ($products as $product)
{
// Load the product page
$link = $context->link->getProductLink($product['id_product']);
file_get_contents($link);
// Print this to screen right away
print "loaded: " . $link . "<br />";
ob_flush();
flush();
// Stop for 0.2 seconds
usleep(200000);
}
Basically I got this problem after SUPEE 7405 update. Whenever I add something to the cart and then click remove item in the AJAX cart, it tells me "Cannot remove the item."
I have to refresh the page and then the item successfully removes.
Basically adding and then instantly removing item=Doesnt work., I need to add, refresh page (or go the other page of site) and then click remove.
i noticed the patch overrode
app/code/core/Mage/Checkout/controllers/CartController.php
Code before the patch
/**
* Delete shoping cart item action
*/
public function deleteAction()
{
$id = (int) $this->getRequest()->getParam('id');
if ($id) {
try {
$this->_getCart()->removeItem($id)
->save();
} catch (Exception $e) {
$this->_getSession()->addError($this->__('Cannot remove the item.'));
Mage::logException($e);
}
}
$this->_redirectReferer(Mage::getUrl('*/*'));
}
Code after the patch
/**
* Delete shoping cart item action
*/
public function deleteAction()
{
if ($this->_validateFormKey()) {
$id = (int)$this->getRequest()->getParam('id');
if ($id) {
try {
$this->_getCart()->removeItem($id)
->save();
} catch (Exception $e) {
$this->_getSession()->addError($this->__('Cannot remove the item.'));
Mage::logException($e);
}
}
} else {
$this->_getSession()->addError($this->__('Cannot remove the item.'));
}
$this->_redirectReferer(Mage::getUrl('*/*'));
}
What did the patch override in my files causing this issue?
You need to update cart item template [design_package/theme]/template/checkout/cart/item/default.phtml
Find <?php echo $this->__('Remove Item') ?>
Replace with
<?php echo $this->__('Remove Item') ?>
As you can see in the deleteAction function, SUPEE7405 added form-key validation to cart deletions to prevent malicious cross-site requests. If you've overridden the cart item template (checkout/cart/item/default.phtml) in your theme, or are using a theme which overrides this template, it will need to be updated to include the formkey hidden input field. You can pull the relevant change across from base/default/checkout/cart/item/default.phtml.
In my case Compilation was enabled. so i realized that compiled files wasnt compatible or recognized new patch (SUPEE 7405)
What did I do?
Remove patch sh patch_name.sh -R
Disable compilation
Clear magento cache
Apply patch again sh patch_name.sh
Clear magento cache again
Enable compilation
Run Compilation process
I hope that helps
I'm having a lot of trouble to change a downloadable product url after a successful order.
Right now I'm listening "sales_model_service_quote_submit_after" and trough :
$order = $observer->getEvent()->getOrder();
$items = $order->getAllItems();
foreach ($items as $product)
{
$links = $product->getProduct()->getDownloadableLinks();
foreach ($links as $link)
{
$link->setLinkUrl('My New Url');
}
}
I'm trying to set a new one.
It works but it seems to be reset to the original value later.
I may need to find an another observer event, but I've no idea which one is the right one.
I also tried the "before", and "success" ones.
Thanks for your precious help :).
See you' !
edit : sales_order_save_before works better ! But it executes more than once. :(
giftcards_observer_sales_order_place_after did the trick.
Usually, I just set a $feedback var or array and then check for that to display in my views.
However, it occurred to me I should perhaps use flashdata instead.
The problem is sometimes - for say an edit record form, I may simply want to reload the form and display feedback - not redirect. when i use flashdata, it shows but then it shows on the next request as well.
What would be the best practice to use here?
CodeIgniter supports "flashdata", or session data that will only be available for the next server request, and are then automatically cleared.
u use hidden field for that
I would use the validation errors from the Form validation class and load those directly to the view in its 2nd argument.
$this->form_validation->set_error_delimiters('<p>', '</p>');
$content_data = array();
if (!$this->form_validation->run()) {
$content_data['errors'] = validation_errors();
}
$this->load->view('output_page', $content_data);
Then check in your view whether $errors isset.
Controller:
$data['message'] = 'some message you want to see on the form';
$this->load->view('yourView', $data);
View:
if (isset ($message)) : echo $message; endif;
...
Here's script being called through ajax:
<?php
require_once '../app/Mage.php';
umask(0);
/* not Mage::run(); */
Mage::app('default');
$cat_id = ($_POST['cat_id']) ? $_POST['cat_id'] : NULL;
try {
$category = new Mage_Catalog_Model_Category();
$category->load($cat_id);
$collection = $category->getProductCollection();
$output = '<ul>';
foreach ($collection as $product) {
$cProduct = Mage::getModel('catalog/product');
$cProduct->load($product->getId());
$output .= '<li><img id="'.$product->getId().'" src="' . (string)Mage::helper('catalog/image')->init($cProduct, 'small_image')->resize(75) . '" class="thumb" /></li>';
}
$output .= '</ul>';
echo $output;
} catch (Exception $e) {
echo 'Caught exception: ', $e->getMessage(), "\n";
}
I'm just passing in the Category ID, which I've tacked onto the navigation links, then doing some work to eventually just pass back all product images in that category.
I'm using this on a drag and drop build-a-bracelet type of application, and the amount of images returned is sometimes in the 500s. So it get's pretty held up during transmission, sometimes 10 seconds or so.
I know I'd do good by caching them some way, just not sure how to go about it. Any help is much appreciated.
Thanks.
-Wes
From the looks of your code, you're probably already "caching" the chosen size of the image. That is, Magento doesn't have to invoke GD to resize the image on the fly.
However, the 500 images still have to be requested from Apache, which is going to be a complete pain the first time no matter what you do. Make sure that Apache is configured to allow browser-size caching of media such as those JPGs for a pretty long period of time and you shouldn't have to re-download the images on every page load.
Aside from that, you may want to devise a strategy to use fewer images and request more only as they are needed. It's unlikely that a user can really focus on 500 images in any meaningful way.
Hope that helps!
Thanks,
Joe