Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can't modify response in a Magento event observer, even though observer is firing

I'm attempting to use an observer to modify the response of the add to cart controller action, but only in the context of an AJAX request.

My observer is called and my JS is retrieving data fine, I have verified this by putting a die() in my observer function cartAdd() and verifying the response developer console, which I am using to see the result of my response from Magento. So JS isn't the issue here.

My primary problem is that I can't seem to modify the response through the normal functions. I get the request by using $observer->getEvent()->getControllerAction()->getResponse() and then make changes to it by setHeader(), or setBody(), or any other function that modifies the response, but there is absolutely no effect to the response!

Does anybody have any clue as to why I'm not able to modify the response in my observer?

In /app/code/local/mynamespace/mymodule/etc/config.xml:

<frontend>
....
    <events>
        <controller_action_predispatch_checkout_cart_add>
            <observers>
                <mymodule_cart_add>
                    <type>singleton</type>
                    <class>mymodule/observer</class>
                    <method>cartAdd</method>
                </mymodule_cart_add>
            </observers>
        </controller_action_predispatch_checkout_cart_add>
    </events>
</frontend>

In /app/code/local/mynamespace/mymodule/Model/Observer.php:

public function cartAdd(Varien_Event_Observer $observer)
{
    $controllerAction = $observer->getEvent()->getControllerAction();
    if($controllerAction->getRequest()->isAjax()) {
        $response = $controllerAction->getResponse();
        // I've even tried using:
        // $response = Mage::app()->getResponse();
        $response->setHeader('HTTP/1.1','403 Forbidden'); //using this because i will need it in my final code and it will make it immediatly obvious the response has been changed
        $response->setHeader('Content-type', 'application/json');
        $response->setBody('hello world!!!!');
        // this is to stop the product from being added to the cart
        $controllerAction->setFlag('', Mage_Core_Controller_Varien_Action::FLAG_NO_DISPATCH, true);
    }
}

Please note: I know this code isn't going to at all AJAXify adding to cart (which is my end goal). At the moment I am just trying to resolve this issue

I end up just getting the contents of the page that you would end up on as a result of running an add to cart action:

An example of the data I am seeing in the console, as shown to me by my JS code

like image 704
Josh Davenport-Smith Avatar asked Sep 14 '12 22:09

Josh Davenport-Smith


1 Answers

When a product is added to cart there is admin-configurable behavior to send a person to the cart page or to redirect them back to the product page. See the System > Configuration > Checkout > Shopping Cart: After Adding a Product Redirect to Shopping Cart field.

This redirect behavior is accomplished via a redirect which will displace any redirect set in the dynamic controller_action_predispatch_checkout_cart_add event; ref. the final bit of logic from the Mage_Checkout_CartController::addAction(). Have no fear, though! Magento core developers have the need to override this behavior as well, so it is possible to inform the Mage_Checkout cart controller's addAction() method to bypass the normal redirect behavior if a flag has been set on the checkout/session object. Not only is there a hook and supporting logic to make it work, but there is actually a working example from the core - always a good thing for developers.

Just prior to the final redirect logic in the addAction() method, the cart controller's addAction() method dispatches the checkout_cart_add_product_complete event. This event is observed by the Mage_Wishlist observer. A quick review of relevant final logic from the Mage_Wishlist_Model_Observer::processAddToCart() method shows how to prevent the cart controller's addAction() method from redirecting - namely by setting the no_cart_redirect flag on checkout/session object, which preserves the redirect set on the response object.

There is one more consideration in this case. It's likely that the Mage_Wishlist observers behavior should be preserved, namely: after adding a product to cart from the wishlist, a customer may be redirected to the next product in their wishlist. This is one of the instances when observer processing order matters. To make sure that the Mage_Wishlist module's add to cart behavior is preserved, other modules which consume the checkout_cart_add_product_complete event should fire before the Mage_Wishlist observer. In the declaration file for the custom module, the Mage_Wishlist module should be set as dependent on the custom module, which will ensure that the custom module's observer will fire before the Mage_Wishlist module:

<?xml version="1.0" encoding="UTF-8"?>
<config>
    <modules>
        <Custom_Module>
            <active>true</active>
            <codePool>local</codePool>
        </Custom_Module>
        <Mage_Wishlist>
            <depends>
                <Custom_Module />
            </depends>
        </Mage_Wishlist>
    </modules>
</config>

If the Mage_Wishlist module were not a factor, the better targeted event to consume would be the dynamically-generated controller_action_postdispatch_checkout_cart_add event, which is the last targeted event before the generic controller_front_send_response_before event.

like image 58
benmarks Avatar answered Sep 30 '22 11:09

benmarks