Using a Controller Observer to Dispatch your Own Event

Sometimes you may find that the big bad Magento Observer Cheatsheet does not cut it. When you want to do a particular thing and there’s no observer for it you kick yourself, because it means you have to inevitably rewrite a block or something silly like that. However there is one more saviour that I stumbled across in somebodies comments on another website earlier last week – using the controller observer to dispatch your events.

Normally events are dispatched within blocks and models – all of which are called by particular controllers depending where you are on a Magento website. However there is a very obscure event that is fired within a controller – in fact it is fired every single time you change pages on Magento – and we can use an observer to observer it.

The event I am talking about is the controller_action_predispatch event located within app>code>core>Mage>Core>Controller>Varien>Action.php – funnily enough you will find this on the cheat sheet. By using an observer on this event we can check what controller/action we are currently on at any time on the website, in theory this means that we can then dispatch our own event when we hit a certain controller action.

Getting confused? Let’s give an example, looking through the cheat sheet I cannot see an observer for a very fundamental part of an e-commerce website – the checkout_cart_product_add_before event. Now there is an “after” event but what good would that be if you are perhaps querying an external stock system and need to know the users selected quantity as they add to basket but before the product is actually placed in their basket? We need to somehow check the stock of that product via an API as it is picked off the shelf and on the way to the cart. Before it reaches the cart we need to know whether or not the customer is allowed their chosen quantity – so we need to stop the add to cart action and send the customer back to the product page with an error message. Therefore we need to run some custom code before the product is added to cart – checkout_cart_product_add_before.

So how does this tie in with our predispatch event? Well we need to fire our checkout_cart_product_add_before when the customer is adding a product to their cart – therefore we know that the customer is going to have to visit a particular controller / action – namely checkout_cart_add – or the addAction() of Checkout/CartController.php.

So first of all we set up an observer to check our predispatch like so (in our config.xml of our module):

<frontend>
<events>
<controller_action_predispatch>
 <observers>
 <add_event>
 <type>singleton</type>
 <class>module/observer</class>
 <method>addEvent</method>
 </add_event>
 </observers>
 </controller_action_predispatch>
</events>
</frontend>

So now we have a php function that we can use to dispatch our own event. Within this php function in your module’s Model>Observer.php we need the following:


public function addEvent($observer)
 {
if($observer->getEvent()->getControllerAction()->getFullActionName() == 'checkout_cart_add')
{
Mage::dispatchEvent('checkout_cart_product_add_before', $observer);
}
return $this;
 }

From the above you can see we are checking out the FullActionName – which we then check is equal to our checkout_cart_add action. If this is the case then we can dispatch our own custom event using the dispatchEvent name above – in our case checkout_cart_product_add_before.

Now we know that the checkout_cart_product_add_before event is being fired – we can add our own observer for it – so lets return to config.xml and amend it so we are now observing our custom event.

<frontend>
<events>
<controller_action_predispatch>
 <observers>
 <add_event>
 <type>singleton</type>
 <class>module/observer</class>
 <method>addEvent</method>
 </add_event>
 </observers>
 </controller_action_predispatch>
<checkout_cart_product_add_before>
 <observers>
 <add_event>
 <type>singleton</type>
 <class>module/observer</class>
 <method>ourCheckoutCartProductAddBeforeFunction</method>
 </add_event>
 </observers>
</checkout_cart_product_add_before>
</events>
</frontend>

Now we can simply add some code into our new function and this will be fired every time we are about to add a product to our cart! The good news is on this example we are using a controller and we know that we are posting data across – so retrieving our product data for use in the function is fairly easy. We simply check the request:


$request = Mage::app()->getRequest()->getPost();
// or
$observer->getEvent()->getControllerAction()->getRequest();

Thanks for reading!