fede.carg / wiki

ZendController 2.0

From Federico Cargnelutti

Jump to: navigation, search

Contents

Issues

Zend_Controller 1.x issues:

  1. Zend_Controller_Front violates the single responsibility principle, each responsibility should be a separate class.
  2. Zend_Controller_Front is not polymorphic and therefore makes the system less tolerant to change in requirements.
  3. Zend_Controller_Front provides data to the Zend_Controller_Dispatcher_Standard object creating control coupling.
  4. Extending Zend_Controller_Dispatcher_Abstract violates the DRY principle.
  5. Zend_Controller_Dispatcher_Standard allows components not only to retrieve directory names and paths, but also to dispatch controllers. This includes Action Controllers and Action Helpers.

Overview

The Front Controller needs one or more paths to directories containing action controllers in order to dispatch the request:

require_once 'Zend/Controller/Front.php';  
$frontController = Zend_Controller_Front::getInstance();   
$frontController->throwExceptions(true);   
$frontController->setControllerDirectoryName('controllers');  
$frontController->setControllerDirectory('../application');
$frontController->dispatch();

To add additional directory names and paths, the user has to create a class that extends Zend_Controller_Dispatcher_Abstract and implements Zend_Controller_Dispatcher_Interface:

require_once 'Zend/Controller/Front.php';  
$frontController = Zend_Controller_Front::getInstance();   
$frontController->throwExceptions(true); 
 
/* Zend_Controller_Dispatcher_Extended violates the DRY priciple */ 
require_once 'Zend/Controller/Dispatcher/Extended.php'; 
$dispatcher = new Zend_Controller_Dispatcher_Extended(); 
$dispatcher->setControllerDirectoryName('controllers');  
$dispatcher->setControllerDirectory('../application');  
$dispatcher->setModelDirectory('../application/models');
 
$frontController->setDispatcher($dispatcher);

Extending the Zend_Controller_Dispatcher_Abstract class leads to the following problems:

Code Duplication

In order to add additional methods, the user has to duplicate the behaviour and internal structure of the Zend_Controller_Dispatcher_Standard class. This approach violates the DRY principle:

abstract class Zend_Controller_Dispatcher_Abstract implements Zend_Controller_Dispatcher_Interface 
{}
 
class Zend_Controller_Dispatcher_Extended extends Zend_Controller_Dispatcher_Abstract
{
    // Required: New behaviour
    public function addModelDirectory($path)
    public function setModelDirectory($path)
    public function getModelDirectory()
 
    // Not required: Existent behaviour
    public function __construct(array $params = array())
    public function formatModuleName($unformatted)
    public function formatClassName($moduleName, $className)
    public function classToFilename($class)
    public function isDispatchable(Zend_Controller_Request_Abstract $request)
    public function dispatch(Zend_Controller_Request_Abstract $request, Zend_Controller_Response_Abstract $response)
    public function loadClass($className)
    public function getControllerClass(Zend_Controller_Request_Abstract $request)
    public function isValidModule($module)
    public function getDefaultControllerClass(Zend_Controller_Request_Abstract $request)
    public function getDispatchDirectory()
    public function getActionMethod(Zend_Controller_Request_Abstract $request)
}

API Inconsistency

Because the Front Controller is a singleton and cannot be subclassed, the user is unable to add additional accessor methods to the Front Controller, therefore there's no consistency in the way the data is provided and retrieved from the Dispatcher:

$frontController->addControllerDirectory('../application'); 
$frontController->getDispatcher()->addModelDirectory('../application/models'); 
$frontController->addModuleDirectory('../application/modules') 
$frontController->getDispatcher()->getDefaultModule();

Refactoring the API

Zend_Controller_Front

class Zend_Controller_Front
{
    protected static $_instance = null;
    protected $_directory = null;
    protected $_router = null;
    protected $_dispatcher = null;
    protected $_request = null;
    protected $_response = null;
    protected $_pluginBroker = null;
    protected $_baseUrl = null;
    protected $_invokeParams = array();
    protected $_returnResponse = false;
    protected $_throwExceptions = false;
 
    private function __clone()
    public static function getInstance()
    public function resetInstance()
    public static function run($controllerDirectory)
    public function setDirectory(Zend_Controller_Directory_Abstract $directory)
    public function getDirectory()
    public function setRequest($request)
    public function getRequest()
    public function setRouter($router)
    public function getRouter()
    public function setDispatcher(Zend_Controller_Dispatcher_Interface $dispatcher)
    public function getDispatcher()
    public function setResponse($response)
    public function getResponse()
    public function setPluginBroker(Zend_Controller_Plugin_Abstract $pluginBroker)
    public function getPluginBroker()
    public function registerPlugin(Zend_Controller_Plugin_Abstract $plugin, $stackIndex = null)
    public function unregisterPlugin($plugin)
    public function hasPlugin($class)
    public function getPlugin($class)
    public function getPlugins()
    public function setBaseUrl($base = null)
    public function getBaseUrl()
    public function setParam($name, $value)
    public function setParams(array $params)
    public function getParam($name)
    public function getParams()
    public function clearParams($name = null)
    public function throwExceptions($flag = null)
    public function returnResponse($flag = null)
    public function dispatch(Zend_Controller_Request_Abstract $request = null, Zend_Controller_Response_Abstract $response = null)
}
Contact
Personal tools