Using Action Helpers in Zend Framework

When you have some functionality that needs to be shared across multiple controllers, one method is to use action helpers. Action helpers are very powerful and contain hooks to automatically run when you need them too, but you can ignore all that if you don't need it.

The first thing you need to do is decide where to put them. The latest default project structure document recommends using a sub folder from your controllers directory. That is: application/controllers/helpers, and it's as good a place as any.

Firstly, you need to tell the helper broker where your action helpers are. I usually do this in the bootstrap, but it could equally be done in a front controller plug-in:


Zend_Controller_Action_HelperBroker::addPath(
APPLICATION_PATH .'/controllers/helpers');

You then need to create your action helper, we'll call it Multiples in this example and so
the filename is application/controllers/helpers/Multiples.php:

<?php

class Zend_Controller_Action_Helper_Multiples extends
Zend_Controller_Action_Helper_Abstract
{
function direct($a)
{
return $a * 2;
}
}

Note that there is a prefix to the action helper name of Zend_Controller_Action_Helper. You can change this by passing a different prefix as the second parameter to the Zend_Controller_Action_HelperBroker::addPath() call in your bootstrap.

Finally, usage within a controller action:

<?php

class IndexController extends Zend_Controller_Action
{
public function indexAction()
{
$this->view->headTitle('Home');
$this->view->title = 'Test of the Multiples action helper';

$number = 30;
$twice = $this->_helper->multiples($number);

$this->view->number = $number;
$this->view-twice = $twice;
}
}

Note that we call the action helper's name as a function of the _helper class. This maps to the direct() call within the helper.

You can put also multiple functions within the action helper:

class Zend_Controller_Action_Helper_Multiples extends
Zend_Controller_Action_Helper_Abstract
{
function direct($a)
{
return $a * 2;
}

function thrice($a)
{
return $a * 3;
}
}

To call the thrice() function within a controller action you use:

$thrice = $this->_helper->multiples->thrice($number);

As you can see if you use the action helper's name as a property of _helper, then you can call any function within the helper.

This is just a summary to get you going. Full details are in the manual.

Have fun and avoid copy and paste with your common functionality!

Zip Files:
I've created an example project so you can see it in context.

28 Responses to “Using Action Helpers in Zend Framework”

  1. 1 F@bio

    Just great!!

    The diference between Action Helpers and Plugin is that plugin can deal with the behave of the request.

    That's right?

  2. 2 Rob...

    F@bio,

    The happen at different points. Action helpers have pre and post hooks too.

    Regards,

    Rob...

  3. 3 Gerard

    $thrice = $this->_helper->multiples->thrice($number);

    Nice! Didn't see that the first time.

  4. 4 Adam

    Great stuff! Thanks for clearing that up.

    One question, how can I use helpers in the view script? Currently I just put them in a random directory and use partial() when I need them, e.g.

    partial('../whatever/foo.phtml', array('foo' => 'bar')) ?>

    Is there a more preferred method?

  5. 5 Dan

    It looks like in a modular structure you could have helper name conflicts. If I have several modules that each provide action helpers I might have

    Zend_Controller_Action_Helper_Test in
    /modules/blog/controllers/helpers

    and

    Zend_Controller_Action_Helper_Test in /modules/support/controllers/helpers

    The helpers are in different directories and are both named test so when you call $this->_helper->test() which one gets called? Or will an exception be thrown somewhere?

    I can see a situation where several developers individually create modules (think Drupal) and provide their own action helpers, but how can you avoid the conflict of naming when regardless of classname prefix, you still have to call $this->_helper->helperName()?

  6. 6 Rob...

    Hi Dan,

    If you have multiple helper paths added to the helper broker, then the last path added is searched first.

    Regards,

    Rob...

  7. 7 Dan

    That makes sense. Classname prefixing like this wouldn't help:

    Blog_Controller_Action_Helper_Test
    Support_Controller_Action_Helper_Test

    because you still have to call $this->_helper->test().

    So I guess to avoid getting intercepted, helpers in my previous example should be named:

    Zend_Controller_Action_Helper_BlogTest
    Zend_Controller_Action_Helper_SupportTest.

    Feels awkward but a small price to pay for the functionality you gain.

    Thanks for the tutorials!

  8. 8 David

    Like F@bio I'm a little confused about the difference between plugins and action helpers. As I understand it, action helpers are for more on demand functionality, while plugins are for things that you'd want to use on every single page, such as authentication for a private system, or some view initialisation code. Is that the case?

  9. 9 Adam

    I've got this working for using helpers in the action. But when I try to use a helper straight from the view script I get "Fatal error: Call to a member function formatDate() on a non-object"

    I've tried (in the view script)...

    $this->view->formatDate();
    and
    $this->_helper->formatDate();

    What am I missing? I have my helper path saved in the bootstrap like explained above and have the correct case for classes etc....? :/

  10. 10 David

    I think you need to assign the helper to the view first, e.g.

    In your controller, $this->view-> multiples = $this->_helper->multiples;

  11. 11 Rob...

    That sounds reasonable - The view doesn't know anything about action helpers otherwise.

    Regards,

    Rob...

  12. 12 Alexander Mahomet

    hello Rob

    I'm thinking about directory structure and name conventions, and i have problem.

    From one side:
    you suggest to name helpers Zend_Controller_Action_Helper_Multiples and put them into application/helpers

    From other side:
    Manual http://framework.zend.com/manual/en/coding-standard.naming-conventions.html#coding-standard.naming-conventions.classes

    IMPORTANT: Code that must be deployed alongside ZF libraries but is not part of the standard or extras libraries (e.g. application code or libraries that are not distributed by Zend) must never start with "Zend_" or "ZendX_"

    That mean that Zend_Controller_Action... doesn't allowed

    And from third side, in Matthew Weier O'Phinney pastebin application
    http://weierophinney.net/matthew/archives/189-Pastebin-app-and-conference-updates.html

    another variant, My_View_Helper_SimpleTextarea for example in directory library/My/View/Helper. It's not an action helper, but idea the same.

    I'm confused, what the best way?

    P.S. Sorry for my english

  13. 13 Rob...

    Hi,

    For action and view helpers, the default prefix is "Zend_Controller_Action" or "Zend_View_Helper", so I would argue that these particular cases are different. It would be helpful if the defaults were App_View_Helper or My_View_Helper though as it would establish the convention for the name of the folder that lives in library that is used for ZF overrides.

    There are two places to put the action helper files: within the library/ folder as per Matthew's pastebin or in the controllers/helpers/ folder as per the official Quickstart. The choice is yours :)

    Regards,

    Rob...

  14. 14 Jonathan Dunn

    Is it ok accessing action helpers from within models?

    Jonathan.

  15. 15 Rob...

    Jonathan,

    I wouldn't. Models should be self-contained.

    Regards,

    Rob...

  16. 16 Jonathan Dunn

    What would you suggest for a function that needs to be executed across multiple models? surely copying and pasting it across multiple models isn't the right way of going about it?

    Thanks!

  17. 17 Rob...

    Jonathan,

    I would write the functionality into a separate model class and use it in the other models.

    Regards,

    Rob...

  18. 18 Jonathan Dunn

    ok that makes sense, thanks rob!

    Jonno.

  19. 19 Mo

    Hi,
    am facing a small problem; am trying to create a view helper with more than just one method.

    for one method it works perfectly, i just call it from the view using $this->MyViewHelperName();

    but, i created another method in the class and when i try to call it.. it fails
    $this->MyViewHelperName()->MethodTwo();

    Any idea how can i make it work?
    Thanks,

  20. 20 Rob...

    Mo,

    Return $this from the function MyViewHelperName::myViewHelperName()

    Regards,

    Rob...

  21. 21 Nikola

    Hi,

    I have a doubt about handling some jobs that needs to be executed across multiple controllers. To be more precise, here are things that need to be done:
    //Setting compile dir for every module, because I use Smarty
    $compile_dir = $this->view->getCompileDir();
    $this->view->setCompileDir($compile_dir . '/' . $this->_request->getModuleName());

    //Getting template dir that user has selected in admin panel.
    $settings = Zend_Registry::get('settings');
    $this->view->theme = $settings['theme_dir'];

    Currently, I keep that code in init() method of every controller. Is there any better solution, maybe with those action helpers?

    Thanks.

  22. 22 Rob...

    Nikola,

    I would use the preDispatch() hook of an action controller to do that.

    Regards,

    Rob...

  23. 23 Nikola

    So you mean just to put those lines from init() to preDispatch()?

    Ok, but there's still a problem of copy/paste that code in every controller, or maybe I misunderstood something? :)

  24. 24 Vibhor

    Hi Rob,

    I am using a modular directory structure for my zend app. Here is the structure:

    Appname

    - frontend

    -modules

    -module1

    -controller

    -models

    -views

    -module2

    -controller

    -models

    -views

    -layouts

    -helpers

    I need to have an action helper for my controllers

    The helpers directory is where my action helper files will reside. In the bootstrap, I have done this:

    $view->addHelperPath(FRONT_APPLICATION_PATH.'/helpers');

    This is the code that I have written for my new helper

    class Zend_Controller_Action_Helper_Cim extends Zend_Controller_Action_Helper_Abstract

    {

    function direct($a) {

    return $a.'from Helper';

    }

    function other($a) {

    echo $a.'from Helper other';

    }

    }

    And this is how I am calling in the controller:

    $leadHelper = $this->_helper->getHelper('cim');

    echo $leadHelper->direct('asdasd');

    I cannot see any error but also I do not see any output. Am I doing something wrong here.

    Thanks,

    Vibhor

  25. 25 Vibhor

    Hi,

    Sorry for the formatting!

    I am using a modular directory structure for my zend app. Here is the structure:

    Appname
     - frontend
       -modules
          -module1
             -controller
             -models
             -views
           -module2
              -controller
              -models
              -views
        -layouts
        -helpers
    

    I need to have an action helper for my controllers

    The helpers directory is where my action helper files will reside. In the bootstrap, I have done this:

    $view->addHelperPath(FRONT_APPLICATION_PATH.'/helpers');

    This is the code that I have written for my new helper

    class Zend_Controller_Action_Helper_Cim extends Zend_Controller_Action_Helper_Abstract

    {

    function direct($a) {

    return $a.'from Helper';

    }

    function other($a) {

    echo $a.'from Helper other';

    }

    }

    And this is how I am calling in the controller:

    $leadHelper = $this->_helper->getHelper('cim');

    echo $leadHelper->direct('asdasd');

    I cannot see any error but also I do not see any output. Am I doing something wrong here.

    Any help will be appreciated.

    Thanks,

    Vibhor

  26. 26 helmi

    Hi Rob

    I'am beginner in zf 1.9 where do i write this code
    [code]
    Zend_Controller_Action_HelperBroker::addPath(
    APPLICATION_PATH .'/controllers/helpers');
    [/code]

    with my version(zf 1.9)

    Thanks

  27. 27 helmi

    ok found it

    [code]

    class Bootstrap extends Zend_Application_Bootstrap_Bootstrap {

    public function run()
    {

    $config = new Zend_Config_Ini(APPLICATION_PATH.'/configs/application.ini');
    // On met notre fichier de config dans un registre.
    Zend_Registry::set('config', $config);
    Zend_Controller_Action_HelperBroker::addPath(
    APPLICATION_PATH .'/controllers/helpers');
    parent::run();
    }

    [/code]

  28. 28 Anil

    In ZF 1.10 we can use like this

    Zend_Controller_Action_HelperBroker::addHelper(new Zend_Controller_Action_Helper_Multiples());

The views expressed in these comments are not the views of the publisher. However, we believe in the rights of others to express their legitimate views and concerns. Any legitimate complaint emailed to rob@akrabat.com will be seriously considered and the post reviewed as desirable and necessary.