Pragmatism in the real world

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 thoughts on “Using Action Helpers in Zend Framework

  1. Just great!!

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

    That's right?

  2. 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?

  3. 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()?

  4. Hi Dan,

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

    Regards,

    Rob…

  5. 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!

  6. 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?

  7. 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….? :/

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

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

  9. 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

  10. 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…

  11. 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!

  12. 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,

  13. 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.

  14. 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? :)

  15. 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

  16. 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

  17. 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

  18. 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]

  19. In ZF 1.10 we can use like this

    Zend_Controller_Action_HelperBroker::addHelper(new Zend_Controller_Action_Helper_Multiples());

Comments are closed.