5.2. Action Helpers

5.2. Action Helpers

In addition to the action helpers provided by Zend Framework, Zym includes many useful helpers that deal with specific tasks. Helpers are located in a similar fashion to ZF as they are located at Zym/Controller/Action/Helper/*.php with the class name prefix of Zym_Controller_Action_Helper_.

5.2.1. FlashRedirector

This helper allows an application to store url to be retrieved on the next request to redirect a user. Common applications for flash redirection is on authentication systems. If a user visits a url that requires them to be logged in, but they are not, they would be redirected to the login page. This helper would store the url in order to redirect the user to the page they requested after login.

Example 5.2. Setting a flash redirect

In this example, we have a plugin that checks if a user is logged in and has access to the requested action. If the user fails the ACL check, we save the current URL and redirect the user to a login page.

<?php
// [...]
// Inside a controller plugin
class My_Auth_Plugin extends Zend_Controller_Plugin_Abstract
{
    /**
     * Predispatch
     *
     * @param Zend_Controller_Request_Abstract $request
     */
    public function preDispatch(Zend_Controller_Request_Abstract $request)
    {
        // Check if user is authenticated
        // [...]
 
        // Store url before redirecting user to login page
        $flashRedirector = Zend_Controller_Action_HelperBroker::getStaticHelper('FlashRedirector');
        $flashRedirector->setRedirect($request->getRequestUri());
 
        // Redirect to login page
        // [...]
    }
}

Example 5.3. Redirecting after login

On the login page, we can use the stored url to redirect the user to their requested page after login. If the user mis-typed their password, we must extend the redirect with extendRedirect() to keep it for the next request. By default, urls are only kept for one request. If you need them for more than one, you can do setExpirationHops(4 /*requests*/) to change the number of requests to keep the url.

After a success, you can either use the builtin redirect functions redirect(array('code' => 303)) or redirectAndExit(); If you would rather process the redirect yourself, you can use getRedirect() to retrieve the url.

You do not have to check if a redirect exists with hasRedirect() although it is recommended.

<?php
class LoginController extends Zend_Controller_Action 
{
    public function loginAction()
    {
        $flashRedirector = $this->getHelper('FlashRedirector');
 
        // Login [...]
 
        if (!$auth) {
            // User failed auth, extend the redirect 
            // and reshow login form
 
            if ($flashRedirector->hasRedirect()) {
                $flashRedirector->extendRedirect();
            }
        } else {
            // Authentication sucess!
            // Redirect to previous requested page
 
            if ($flashRedirector->hasRedirect()) {
                $flashRedirector->redirect();
 
                // $flashRedirector->redirectAndExit();
            }
        }
    }
}

5.2.2. Form

Writing applications using Zend_Form can cause you to end up with a handful of custom form classes without a clean place to put them. The Zym_Controller_Action_Helper_Form action helper will allow you to load or create form classes from a specified convention.

The default convention of the form helper is ":moduleDir/forms/:action.php". Translated, this means the form will be loaded from the current module inside "forms" folder. If you are currently inside "Foo" module and "Bar" controller, with the requested form being "Example", then it will load "pathToModule/forms/Example.php".

Example 5.4. Simple creation of forms

A form can be simply loaded from the action like so...

<?php
class Foo_BarController extends Zend_Controller_Action 
{
    public function indexAction()
    {
        // Loads from current module 'Foo'/forms/Example.php
        $form = $this->getHelper('Form')->create('Example');
 
        $this->view->form = $form;
    }
}

Example 5.5. Simple shorthand creation of forms

A short hand version of creating form objects is just create() without params. It will load a form with the name [CurrentController][CurrentAction]. In other words, IndexController::fooAction() would result in IndexFoo.php form.

<?php
class Foo_BarController extends Zend_Controller_Action 
{
    public function indexAction()
    {
        // Loads from current module 'Foo'/forms/BarIndex.php
        $form = $this->getHelper('Form')->create();
 
        $this->view->form = $form;
    }
}

Aside from creation of form objects, the form action helper also supports loading of form classes from those folders using the load($name) function.

5.2.2.1. Changing form loading path conventions

While default conventions will work for the majority of us, there are still situations where you might want to break convention to use a certain directory structure. The form action helper is flexible enough to bend to your desire. To change path conventions, we need to change the path spec via the setPathSpec() function. The default path spec is ":moduleDir/forms/:action.php", below is a list of available options.

:moduleDir
:module
:controller
:action

5.2.3. Navigation

The navigation action helper simplifies the retrieval of the navigation object from either the registry under the key "Zym_Navigation" or by storing an internal reference through setNavigation() or the navigation constructor parameter. For simplicity and consistency with ZF, this helper will retrieve the object from the registry if possible.

Example 5.6. Using the navigation action helper

<?php
// Bootstrap
Zend_Registry::set('Zym_Navigation', new Zym_Navigation());
 
// Inside controller action
class IndexController extends Zend_Controller_Action
{
    public function indexAction()
    {
        $helper     = $this->getHelper('Navigation');
        $navigation = $helper->getNavigation();
 
        // Direct method
        $navigation = $this->_helper->navigation();
    }
}

5.2.4. Translator

The translator action helper is similar to ZF's translate view helper (Zend_View_Helper_Translate). The api of this helper is almost 1:1 and the same goes for usage. This helper allows easy access and usage of a global translate object under the registry key "Zend_Translate" which is used throughout ZF or one stored internally through setTranslator(). It also supports a translate object during construction.

Example 5.7. Using the translator action helper

<?php
// Bootstrap
$translate = new Zend_Translate('gettext', '../data');
Zend_Registry::set('Zend_Translate', $translate);
 
// Inside controller action
class IndexController extends Zend_Controller_Action
{
    public function indexAction()
    {
        $helper = $this->getHelper('Translator');
        $text   = $helper->translate('foo');
        $text   = $helper->translate('foo %s', 'placeholder');
 
        // Short syntax
        $text   = $helper->_('foo');
 
        // Direct method
        $text = $this->_helper->translator('test');
        $text = $this->_helper->translator('test %s', 'placeholder');
 
        // Output different locale using last param
        $locale = new Zend_Locale('en_US');
        $text = $this->_helper->translator('test', $locale);
        $text = $this->_helper->translator('test', 'de');
        $text = $this->_helper->translator('test %s', 'placeholder', $locale);
    }
}