ZF-5628: ContextSwitch not working with routers

Description

The bug with a Zend_Controller_Action_Helper_ContextSwitch

When using custom routes it will not work at all. In function public function initContext($format = null)..... $action = $request->getActionName(); This action will be always null so context will not be switched.

By changing it to $action = $request->getActionName(); if (empty($action)) { $action = Zend_Controller_Front::getInstance()->getDefaultAction(); } It working fine.

Comments

We are running into this same issue with ZF 1.11.5. I'd be willing to help patch this, but is @ivan fix the correct way to fix this, or is there a better place?

In ZendFramework-1.11.10 this problem still exists. I tried using a different layout for mobile devices with Zend_Controller_Action_Helper_ContextSwitch. After a long time searching for bugs in my code, I Googled and ran into this bug report.

The problem lies much deeper than Zend_Controller_Request_Http. The problem is that the default controller (index) and the default action (index) are never being set by the Router at all. The router fully relies on the config file as this code shows:


public static function getInstance(Zend_Config $config)
{
    $defs = ($config->defaults instanceof Zend_Config) ? $config->defaults->toArray() : array();
    $map = ($config->map instanceof Zend_Config) ? $config->map->toArray() : array();
    $reverse = (isset($config->reverse)) ? $config->reverse : null;
    return new self($config->route, $defs, $map, $reverse);
}

public function __construct($route, $defaults = array(), $map = array(), $reverse = null)
{
    $this->_regex    = $route;
    $this->_defaults = (array) $defaults;
    $this->_map      = (array) $map;
    $this->_reverse  = $reverse;
}

Zend_Controller_Dispatcher_Standard on the other hand does know what the default action and the default controller are, because they are inherited from Zend_Controller_Dispatcher_Abstract where they are both hardcoded as properties. They are however never passed to the request object.

When the controller name or action name is missing in Zend_Controller_Request_Http this should (in my opinion) raise an exception so that users know what the problem is, because other functionality breaks when these parameters are missing. An other solutions could be setting the default controller and default action in Zend_Controller_Request_Http. They are documented as the default value when not provided by the user, but when the user forgets them, they are not being set.

See: http://framework.zend.com/manual/en/… ??If no action is provided, the action index is assumed, and if no controller is provided, the controller index is assumed (following the Apache convention that maps a DirectoryIndex automatically).??

The easiest fix for now is too hardcode the controller and action in the routing.

This does not work when using ContextSwitch:


resources.router.routes.default.type = "Zend_Controller_Router_Route_Regex"
resources.router.routes.default.route = "([a-z0-9]*(?:/[a-z0-9]+)*)"
resources.router.routes.default.defaults.module = "default"
resources.router.routes.default.map.1 = "page"

This does work when using ContextSwitch:


resources.router.routes.default.type = "Zend_Controller_Router_Route_Regex"
resources.router.routes.default.route = "([a-z0-9]*(?:/[a-z0-9]+)*)"
resources.router.routes.default.defaults.module = "default"
resources.router.routes.default.defaults.controller = "index"
resources.router.routes.default.defaults.action = "index"
resources.router.routes.default.map.1 = "page"

It would be nice if this bug gets fixed after more than 2 and a half years. If more info is needed, just let me know.