7.8. Action Helpers

7.8.1. Introduction

Action Helpers allow developers to inject runtime and/or on-demand functionality into any Action Controllers that extend Zend_Controller_Action. Action Helpers aim to minimize the necessity to extend the abstract Action Controller in order to inject common Action Controller functionality.

There are a number of ways to use Action Helpers. Action Helpers employ the use of a brokerage system, similar to the types of brokerage you see in Zend_View_Helpers, and that of Zend_Controller_Plugin. Action Helpers (like Zend_View_Helpers) may be loaded and called on demand, or they may be instantiated at request time (bootstrap) or action controller creation time (init()). To understand this more fully, please see the usage section below.

7.8.2. Helper Initialization

A helper can be initialized in several different ways, based on your needs as well as the functionality of that helper.

The helper broker is stored as the $_helpers member of Zend_Controller_Action; use the broker to retrieve or call on helpers. Some methods for doing so include:

  • Explicitly using getHelper(). Simply pass it a name, and a helper object is returned:

    $flashMessenger = $this->_helpers->getHelper('FlashMessenger');
    $flashMessenger->addMessage('We did something in the last request');
    
  • Use the helper broker's __get() functionality and retrieve the helper as if it were a member property of the broker:

    $flashMessenger = $this->_helpers->FlashMessenger;
    $flashMessenger->addMessage('We did something in the last request');
    
  • Finally, most action helpers implement the method direct() which will call a specific, default method in the helper. In the example of the FlashMessenger, it calls addMessage():

    $this->_helpers->FlashMessenger('We did something in the last request');
    
[Note] Note

All of the above examples are functionally equivalent.

You may also instantiate helpers explicitly. You may wish to do this if using the helper outside of an action controller, or if you wish to pass a helper to the helper broker for use by any action. Instantiation is as per any other PHP class.

7.8.3. The Helper Broker

Zend_Controller_Action_HelperBroker handles the details of registering helper objects and helper paths, as well as retrieving helpers on-demand.

To register a helper with the broker, use addHelper:

Zend_Controller_Action_HelperBroker::addHelper($helper);

Of course, instantiating and passing helpers to the broker is a bit time and resource intensive, so two methods exists to automate things slightly: addPrefix() and addPath().

  • addPrefix() takes a class prefix and uses it to determine a path where helper classes have been defined. It assumes the prefix follows Zend Framework class naming conventions.

    // Add helpers prefixed with My_Action_Helpers in My/Action/Helpers/
    Zend_Controller_Action_HelperBroker::addPrefix('My_Action_Helpers');
    
  • addPath() takes a directory as its first argument and a class prefix as the second argument (defaulting to 'Zend_Controller_Action_Helper'). This allows you to map your own class prefixes to specific directories.

    // Add helpers prefixed with Helper in Plugins/Helpers/
    Zend_Controller_Action_HelperBroker::addPath('./Plugins/Helpers', 'Helper');
    

Since these methods are static, they may be called at any point in the controller chain in order to dynamically add helpers as needed.

7.8.4. Built-in Action Helpers

Zend Framework includes two action helpers by default, a FlashMessenger for handling session flash messages, and a Redirector, to provide different implementations for redirecting to internal and external pages from your application.

7.8.4.1. FlashMessenger

7.8.4.1.1. Introduction

The FlashMessenger helper allows you to pass messages that the user may need to see on the next request. To accomplish this, FlashMessenger uses Zend_Session_Namespace to store messages for future or next request retrieval. It is generally a good idea that if you plan on using Zend_Session or Zend_Session_Namespace, that you initialize with Zend_Session::start() in your bootstrap file. (See Zend Session for more details on its usage.)

7.8.4.1.2. Basic Usage Example

The usage example below shows the use of the flash messenger at its most basic. When the action /some/my is called, it adds the flash message "Record Saved!" A subsequent request to the action /some/my-next-request will retrieve it (and thus delete it as well).

<?php
class SomeController extends Zend_Controller_Action
{
    /**
     * FlashMessenger
     *
     * @var Zend_Controller_Action_Helper_FlashMessenger
     */
    protected $_flashMessenger = null;
    
    
    public function init()
    {
        $this->_flashMessenger = $this->_helpers->getHelper('FlashMessenger');
        $this->initView();
    }
    
    public function myAction()
    {
        /**
         * default method of getting Zend_Controller_Action_Helper_FlashMessenger
         * instance on-demand
         */
        $this->_flashMessenger->addMessage('Record Saved!');
    }

    public function myNextRequestAction()
    {
        $this->view->messages = $this->_flashMessenger->getMessages();
        $this->render();
    }
}

7.8.4.2. Redirector

7.8.4.2.1. Introduction

The Redirector helper allows you to use a redirector object to fufill your application's needs for redirecting to a new URL. It provides numerous benefits over the _redirect() method, such as being able to preconfigure sitewide behavior into the redirector object or using the built in goto($action, $controller, $module, $params) interface similar to that of Zend_Controller_Action::_forward().

The Redirector has a number of methods that can be used to affect the behaviour at redirect:

  • setCode() can be used to set the HTTP response code to use during the redirect.

  • setExit() can be used to force an exit() following a redirect. By default this is true.

  • setGoto() can be used to set a default URL to use if none is passed to goto(). Uses the API of Zend_Controller_Action::_forward(): setgoto($action, $controller = null, $module = null, array $params = array());

  • setGotoRoute() can be used to set a URL based on a registered route. Pass in an array of key/value pairs and a route name, and it will assemble the URL according to the route type and definition.

  • setGotoUrl() can be used to set a default URL to use if none is passed to gotoUrl(). Accepts a single URL string.

  • setPrependBase() can be used to prepend the request object's base URL to a URL specified with setGotoUrl(), gotoUrl(), or gotoUrlAndExit().

Additionally, there are a variety of methods in the redirector for performing the actual redirects:

  • goto() uses setGoto() (_forward()-like API) to build a URL and perform a redirect.

  • gotoRoute() uses setGotoRoute() (route-assembly) to build a URL and perform a redirect.

  • gotoUrl() uses setGotoUrl() (URL string) to build a URL and perform a redirect.

Finally, you can determine the current redirect URL at any time using getRedirectUrl().

7.8.4.2.2. Basic Usage Examples

Exemple 7.1. Setting Options

This example overrides several options, including setting the HTTP status code to use in the redirect ('303'), not defaulting to exit on redirect, and defining a default URL to use when redirecting.

<?php
class SomeController extends Zend_Controller_Action
{
    /**
     * Redirector - defined for code completion
     *
     * @var Zend_Controller_Action_Helper_Redirector
     */
    protected $_redirector = null;
    
    public function init()
    {
        $this->_redirector = $this->_helpers->getHelper('Redirector');
        
        // Set the default options for the redirector
        // Since the object is registered in the helper broker, these become
        // relevant for all actions from this point forward
        $this->_redirector->setCode('303')
                          ->setExit(false)
                          ->setGoto("this-action", "some-controller");
    }
    
    public function myAction()
    {
        /* do some stuff */

        // Redirect to a previously registered URL, and force an exit to occur
        // when done:
        $this->_redirector->redirectAndExit();
        return; // never reached
    }
}
?>

Exemple 7.2. Using Defaults

This example assumes that the defaults are used, which means that any redirect will result in an immediate exit().

<?php
// ALTERNATIVE EXAMPLE
class AlternativeController extends Zend_Controller_Action
{
    /**
     * Redirector - defined for code completion
     *
     * @var Zend_Controller_Action_Helper_Redirector
     */
    protected $_redirector = null;
    
    public function init()
    {
        $this->_redirector = $this->_helpers->getHelper('Redirector');
    }
    
    public function myAction()
    {
        /* do some stuff */

        $this->_redirector->gotoUrl('/my-controller/my-action/param1/test/param2/test2');
        return; // never reached since default is to goto and exit
    }
}
?>

Exemple 7.3. Using goto()'s _forward() API

goto()'s API mimics that of Zend_Controller_Action::_forward(). The primary difference is that it builds a URL from the parameters passed, and using the default :module/:controller/:action/* format of the default router. It then redirects instead of chaining the action.

<?php
class ForwardController extends Zend_Controller_Action
{
    /**
     * Redirector - defined for code completion
     *
     * @var Zend_Controller_Action_Helper_Redirector
     */
    protected $_redirector = null;
    
    public function init()
    {
        $this->_redirector = $this->_helpers->getHelper('Redirector');
    }
    
    public function myAction()
    {
        /* do some stuff */

        // Redirect to 'my-action' of 'my-controller' in the current module,
        // using the params param1 => test and param2 => test2
        $this->_redirector->goto('my-action', 'my-controller', null, array('param1' => 'test', 'param2' => 'test2'));
    }
}
?>

Exemple 7.4. Using route assembly with gotoRout()

The following example uses the router's assemble() method to create a URL based on an associative array of parameters passed. It assumes the following route has been registered:

<?php
$route = new Zend_Controller_Router_Route(
    'blog/:year/:month/:day/:id',
    array('controller' => 'archive', 'module' => 'blog', 'action' => 'view')
);
$router->addRoute('blogArchive', $route);
?>

Given an array with year set to 2006, month to 4, day to 24, and id to 42, it would then build the URL /blog/2006/4/24/42.

<?php
class BlogAdminController extends Zend_Controller_Action
{
    /**
     * Redirector - defined for code completion
     *
     * @var Zend_Controller_Action_Helper_Redirector
     */
    protected $_redirector = null;
    
    public function init()
    {
        $this->_redirector = $this->_helpers->getHelper('Redirector');
    }
    
    public function returnAction()
    {
        /* do some stuff */

        // Redirect to blog archive. Builds the following URL:
        // /blog/2006/4/24/42
        $this->_redirector->gotoRoute(
            array('year' => 2006, 'month' => 4, 'day' => 24, 'id' => 42),
            'blogArchive'
        );
    }
}
?>

7.8.5. Writing Your Own Helpers

Action helpers extend Zend_Controller_Action_Helper_Abstract, an abstract class that provides the basic interface and functionality required by the helper broker. These include the following methods:

  • setActionController() is used to set the current action controller.

  • init(), triggered by the helper broker at instantiation, can be used to trigger initialization in the helper; this can be useful for resetting state when multiple controllers use the same helper in chained actions.

  • preDispatch(), is triggered prior to a dispatched action.

  • postDispatch() is triggered when a dispatched action is done -- even if a preDispatch() plugin has skipped the action. Mainly useful for cleanup.

  • getRequest() retrieves the current request object.

  • getResponse() retrieves the current response object.

  • getName() retrieves the helper name. It retrieves the portion of the class name following the last underscore character, or the full class name otherwise. As an example, if the class is named Zend_Controller_Action_Helper_Redirector, it will return Redirector; a class named FooMessage will simply return itself.

You may optionally include a direct() method in your helper class. If defined, it allows you to treat the helper as a method of the helper broker, in order to allow easy, one-off usage of the helper. As an example, the redirector defines direct() as an alias of goto(), allowing use of the helper like this:

<?php
// Redirect to /blog/view/item/id/42
$this->_helper->redirector('item', 'view', 'blog', array('id' => 42));
?>

Internally, the helper broker's __call() method looks for a helper named redirector, then checks to see if that helper has a defined direct class, and calls it with the arguments provided.

Once you have created your own helper class, you may provide access to it as described in the sections above.