Simplifying Zend_View_Helper_Url

July 12, 2008

When I first began working with Zend_View on a project at work, I noticed that the URL view helper was a bit of a pain to use. It was rare that I didn't want to specify one or more of the action, controller, and module in my call along with the other Route assembly parameters. Having to label them with an array index made the calls to the helper ugly and more difficult to read. As well, I often wanted to refer to actions in the same controller or controllers in the same module with respect to the current action.

To get around this, I wrote a view helper that extended Zend_View_Helper_Url and had three optional parameters specifically for the action, controller, and module. Everything else was passed into the fourth parameter, an associative array of any other parameters I needed to include. If any component of the route is excluded or specified as null, I simply get its value from the current request.

My friend Andy Best took this a step further and added in support for specifying custom routes, which he's using for a project of his own but I didn't need myself because I only use the default routes provided by the standard rewrite router. The result is the code below.

<?php

require_once 'Zend/Controller/Front.php';
require_once 'Zend/View/Helper/Url.php';

class App_View_Helper_Route extends Zend_View_Helper_Url
{
    public function route($action = null, $controller = null, 
        $module = null, $params = array(), $route = null)
    {
        $front = Zend_Controller_Front::getInstance();
        $request = $front->getRequest();
        $router = $front->getRouter();
                                                
        if ($action === null) {
            $action = $request->getActionName();
        }
        if ($controller === null) {
			$controller = $request->getControllerName();
        }
        if ($module === null) {
            $module = $request->getModuleName();
        }

        $urlOptions = array_merge($params, array(
			'controller' => $controller,
            'module' => $module
		));

        if ($router->hasRoute($controller) && $route === null) {
            $route = $controller;
        } elseif ($route === null) {
            $route = 'default';
        }

        return $this->url($urlOptions, $route, true);
    }
}