# El Despachador

## Introducción

Despachar es el proceso de tomar el objeto solicitud, `Zend_Controller_Request_Abstract` , extraer el nombre del módulo, el nombre del controlador, el nombre de la acción, y los parámetros opcionales contenido en él, y luego instanciar un controlador y llamar una acción de ese controlador. Si no se encuentra algún módulo, controlador o acción, se usarán los valores por defecto para ellos. `Zend_Controller_Dispatcher_Standard` especifica index para cada uno de los controladores y acciones por defecto y default para el valor por defecto del módulo, pero permite al desarrollador cambiar los valores por defecto para cada uno usando los métodos `setDefaultController()` , `setDefaultAction()` , y `setDefaultModule()` respectivamente.

### Módulo por Defecto

Cuando se crean aplicaciones modulares, puede encontrarse queriendo también el namespace por defecto del módulo (la configuración por defecto es que el módulo por defecto es no namespaced). Como de 1.5.0, ahora puede hacerlo especificando el prefixDefaultModule como `TRUE` tanto en el front controller como es su despachador:

    // En su front controller:
    $front->setParam('prefixDefaultModule', true);

    // En su despachador:
    $dispatcher->setParam('prefixDefaultModule', true);

Esto le permite re-determinar un módulo existente para ser el módulo por defecto para una solicitud.

El proceso de despachar tiene lugar en un bucle en el front controller. Antes de llevarse a cabo el despacho, el front controller rutea la solicitud para encontrar valores especificados por el usuario para el módulo, controlador, acción, y los parámetros opcionales. A continuación entra en un loop de despacho, despachando la solicitud.

Al comienzo de cada iteración, establece un flag en el objeto solicitud indicando que la acción se ha despachado. Si una acción o un plugin pre o postDispatch resetea ese flag, el loop de despacho continuará e intentará despachar la nueva solicitud. Cambiando el controlador y/o la acción en la solicitud y reseteando el flag despachado, el desarrollador puede definir una cadena de peticiones a realizar.

El método del controlador de acción que controla ese despacho es `_forward()` ; llamar a este método para cualquiera de los pre/postDispatch() o métodos de acción, proporcionando un controlador de acciónes, módulo y, opcionalmente cualquier parámetro adicional que desee enviar a la nueva acción:

    public function fooAction()
    {
        // adelantar a otra acción en el controlador y módulo actuales:
        $this->_forward('bar', null, null, array('baz' => 'bogus'));
    }

    public function barAction()
    {
        // adelantar a una acción en otro controlador:
        // FooController::bazAction(),
        // en el módulo actual:
        $this->_forward('baz', 'foo', null, array('baz' => 'bogus'));
    }

    public function bazAction()
    {
        // adelantar a una acción en otro controlador en otro módulo,
        // Foo_BarController::bazAction():
        $this->_forward('baz', 'bar', 'foo', array('baz' => 'bogus'));
    }

## Subclaseando el Despachador

`Zend_Controller_Front` llamará en primer lugar al router para determinar la primera acción en la solicitud. A continuación se entra en un loop de despacho, el cual llama al despachador para despachar la acción.

El despachador necesita de una variedad de datos a fin de hacer su trabajo - necesita saber cómo formatear los nombres del controlador y de la acción, dónde mirar para los archivos de clase del controlador, cuándo el nombre de un controlador provisto es válido o no, y una API para determinar si una determinada solicitud es incluso despachable basado en la otra información disponible.

`Zend_Controller_Dispatcher_Interface` define los siguientes métodos como necesarios para cualquier implementación de un despachador:

    interface Zend_Controller_Dispatcher_Interface
    {
        /**
         * Formatea un string dentro del nombre de clase del controlador.
         *
         * @param string $unformatted
         * @return string
         */
        public function formatControllerName($unformatted);

        /**
         * Formatea un string dentro de un nombre de método de acción.
         *
         * @param string $unformatted
         * @return string
         */
        public function formatActionName($unformatted);

        /**
         * Determina si la solicitud es despachable
         *
         * @param  Zend_Controller_Request_Abstract $request
         * @return boolean
         */
        public function isDispatchable(
            Zend_Controller_Request_Abstract $request
        );

        /**
         * Establece un parámetro de usuario (via front controller, o para uso local)
         *
         * @param string $name
         * @param mixed $value
         * @return Zend_Controller_Dispatcher_Interface
         */
        public function setParam($name, $value);

        /**
         * Establece un array de parámetros de usuario
         *
         * @param array $params
         * @return Zend_Controller_Dispatcher_Interface
         */
        public function setParams(array $params);

        /**
         * Recupera un único parámetro de usuario
         *
         * @param string $name
         * @return mixed
         */
        public function getParam($name);

        /**
         * Recupera todos los parámetros de usuario
         *
         * @return array
         */
        public function getParams();

        /**
         * Limpia el stack de parámetros de usuario, o un único parámetro de usuario
         *
         * @param null|string|array single key or array of keys for
         *        params to clear
         * @return Zend_Controller_Dispatcher_Interface
         */
        public function clearParams($name = null);

        /**
         * Establece el objeto respuesta a usar, si hubiera alguno
         *
         * @param Zend_Controller_Response_Abstract|null $response
         * @return void
         */
        public function setResponse(
            Zend_Controller_Response_Abstract $response = null
        );

        /**
         * Recupera el objeto respuesta, si hubiera alguno
         *
         * @return Zend_Controller_Response_Abstract|null
         */
        public function getResponse();

        /**
         * Agrega un directorio de controladoes al stack de directorios de controladores
         *
         * @param string $path
         * @param string $args
         * @return Zend_Controller_Dispatcher_Interface
         */
        public function addControllerDirectory($path, $args = null);

        /**
         * Establece el directorio (o directorios) donde se almacenan los archivos
         * de controladoes
         *
         * @param string|array $dir
         * @return Zend_Controller_Dispatcher_Interface
         */
        public function setControllerDirectory($path);

        /**
         * Regresa el directorio(s) actualmente establecido para el lookup de los
         * archivos de controladores
         *
         * @return array
         */
        public function getControllerDirectory();

        /**
         * Despacha una solicitud a una acción de (módulo/)controlador.
         *
         * @param  Zend_Controller_Request_Abstract $request
         * @param  Zend_Controller_Response_Abstract $response
         * @return Zend_Controller_Request_Abstract|boolean
         */
        public function dispatch(
            Zend_Controller_Request_Abstract $request,
            Zend_Controller_Response_Abstract $response
        );

        /**
         * Si un módulo dado es válido o no
         *
         * @param string $module
         * @return boolean
         */
        public function isValidModule($module);

        /**
         * Recuperar el nombre por defecto del módulo
         *
         * @return string
         */
        public function getDefaultModule();

        /**
         * Recuperar el nombre por defecto del controlador
         *
         * @return string
         */
        public function getDefaultControllerName();

        /**
         * Recuperar la acción por defecto
         *
         * @return string
         */
        public function getDefaultAction();
    }

En muchos casos, sin embargo, simplemente debe extender la clase abstracta `Zend_Controller_Dispatcher_Abstract` , en el que cada uno de estas ya han sido definidas, o `Zend_Controller_Dispatcher_Standard` para modificar la funcionalidad del despachador estándar.

Las posibles razones para subclasear al despachador incluye un deseo de utilizar un esquema diferente para nombrar las clases o métodos en sus controladores de acción, o el deseo de utilizar otro paradigma de despacho como ser despachar los archivos de acción bajo directorios de controladores (en lugar de despacharlos a los métodos de clase).