Hooks in Action Helpers
Following on from the discussion on Zend Framework Action Helpers, let’s talk about hooks within them.
Hooks are a feature of action helpers that allow you to automatically run code at certain points in the dispatch cycle. Specially, there are two hook functions available for action helpers:
- preDispatch(): runs before the action function is called
- postDispatch(): runs after the action function has completed
These allow you to ensure that some functionality is always run for each request. Let’s consider a simple example of displaying a random quote in the footer of a website.
We start with an action helper in our controllers/helpers directory called Quote:
<?php
class Zend_Controller_Action_Helper_Quote extends Zend_Controller_Action_Helper_Abstract
{
function preDispatch()
{
$view = $this->getActionController()->view;
$view->footerQuote = $this->getQuote();
}
function getQuote()
{
$quotes[] = 'I want to run, I want to hide, I want to tear down the walls';
$quotes[] = 'One man come in the name of love, One man come and go';
return $quotes[rand(0, count($quotes)-1)];
}
}
The preDispatch() method, collects the view from the action controller and then assigns a random quote to the footerQuote property.
We need to tell the helper broker that we want this helper’s hooks to be run, so in addition to the addHelperPath() call, our bootstrap requires a call to addHelper(). The bootstrap therefore has this code within it:
// Action Helpers
Zend_Controller_Action_HelperBroker::addPath(
APPLICATION_PATH .'/controllers/helpers');
$hooks = Zend_Controller_Action_HelperBroker::getStaticHelper('Quote');
Zend_Controller_Action_HelperBroker::addHelper($hooks);
As we used addPath() to tell the helper broker where to find the action helpers, we can use getStaticHelper() as an easy way to instantiate the class without having to require() and then call new. We can then register it with the helper broker using addHelper().
As the quote is displayed in the footer, the HTML required lives in layout.phtml:
<div id="footer">
<div id="quote">
<?php echo $this->footerQuote; ?>
</div>
</div>
That’s it – not too hard, is it?
Zip Files:
I’ve updated the example project from the last post so you can see it in context.
- ZF_Action_Helper_example.zip – 9.7kB
- ZF_Action_Helper_example_with_zf.zip (including ZF 1.6) – 3.5MB
So what's the difference between an helper like this and a front controller plugin?
Why hooks in getStaticHelper('Hooks'); ?
i dont see any link between your actionhelper and your bootstrap, AND your layout. You call footerQuote from your layout but the helper is called Quote? i dont see the link
Cool!
BTW, in the example code, it should be getStaticHelper('Quote'), right? :)
thanks,
eddie
Thank you!!! I now have one place with all the logic for the stuff like templates that is on every page instead of copied and pasted action helper calls – much nicer :)
eddie,
oops :)
Thanks!
Regards,
Rob…
Christian,
The Quote helper creates a view property called "footerQuote" which is then used in layout.phtml.
There was a bug in the bootstrap code, which is now fixed!
Regards,
Rob…
Lorna,
Glad it was helpful :)
Regards,
Rob…
hi, it's eddie again.
I just downloaded the updated ZF_Action_Helper_example.zip, but the "getStaticHelper('Hooks')" still in the bootstrap.php :)
really very informative tutorial Rob…
Hi Rob!
Very usefull post. Thanks.
I translate it to Russian if you don't mind.
Rob,
//return $quotes[rand(0, count($quotes)-1)];//
Greate Rob, Thanks Lot
Hi Rob,
So how would this code need to be modified to work in ZF 1.8+ ?
Joe,
It shouldn't need any changes except to double check that the method signatures haven't changed.
Regards,
Rob…
I was wondering about if the bootstrap section needed to change? Does that just go into Bootstrap.php?
" // Action Helpers
Zend_Controller_Action_HelperBroker::addPath(
APPLICATION_PATH .'/controllers/helpers');
$hooks = Zend_Controller_Action_HelperBroker::getStaticHelper('Quote');
Zend_Controller_Action_HelperBroker::addHelper($hooks);"
Well, it needs to go somewhere in your bootstrapping process, so creating an _initActionHelpers() isn't a bad idea.
Regards,
Rob…
Thanks for the informative post! I was stuck for hours trying to get this working. Now I have a custom context switcher that gets auto-run from an action helper. This makes for a very clean solution.
Rob's idea helped me get this to work in 1.8+
I'm all for cleanly moving this kind of ancillary functionality – random quotes in a footer or sidebar, for example – out into a separate class. But an action helper seems an odd place for it. It seems to me an action helper is most useful for functionality that can be be called on demand from within an action itself. The kind of action-independent content we are discussing here strikes me as better suited to a view helper, kind of in-keeping with the "controllers are not the data police" philosophy. Whaddya think?
Note if you're doing something that's a bit more complex in your Action Helper…iow, something that might call Exceptions, be sure to check out my issue and resolution on Stack Overflow:
http://stackoverflow.com/questions/4076578/do-action-helpers-with-hooks-to-auto-run-throw-exceptions-or-not/4082325
Hey Rob,
Another thought. Is it possible to get this working from the application.ini configs?
Hey Rob,
Another thought. Is it possible to get this working from the application.ini configs?