<?xml version="1.0" encoding="UTF-8"?>
<!-- EN-Revision: 15103 -->
<!-- Reviewed: no -->
<sect1 id="zend.controller.dispatcher">
    <title>El Despachador</title>

    <sect2 id="zend.controller.dispatcher.overview">
        <title>Introducción</title>

        <para>
            Despachar es el proceso de tomar el objeto solicitud,
            <classname>Zend_Controller_Request_Abstract</classname>,
            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.
            <classname>Zend_Controller_Dispatcher_Standard</classname>
            especifica <methodname>index</methodname> para cada uno de los controladores y
            acciones por defecto y <methodname>default</methodname> para el valor por
            defecto del módulo, pero permite al desarrollador cambiar los
            valores por defecto para cada uno usando los métodos
            <methodname>setDefaultController()</methodname>,
            <methodname>setDefaultAction()</methodname>, y <methodname>setDefaultModule()</methodname>
            respectivamente.
        </para>

        <note>
            <title>Módulo por Defecto</title>

            <para>
                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
                <emphasis>no</emphasis> namespaced).
                Como de 1.5.0, ahora puede hacerlo especificando el
                <methodname>prefixDefaultModule</methodname> como verdadero tanto en el
                front controller como es su despachador:
            </para>

             <programlisting language="php"><![CDATA[
// En su front controller:
$front->setParam('prefixDefaultModule', true);

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

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

        <para>
            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.
        </para>

        <para>
            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/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.
        </para>

        <para>
            El método del controlador de acción que controla ese despacho es
            <methodname>_forward()</methodname>; 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:
        </para>

         <programlisting language="php"><![CDATA[
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'));
}
]]></programlisting>
    </sect2>

    <sect2 id="zend.controller.dispatcher.subclassing">
        <title>Subclaseando el Despachador</title>

        <para>
            <classname>Zend_Controller_Front</classname> 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.
        </para>

        <para>
            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.
        </para>

        <para>
            <classname>Zend_Controller_Dispatcher_Interface</classname>
            define los siguientes métodos como necesarios para cualquier
            implementación de un despachador:
        </para>

         <programlisting language="php"><![CDATA[
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();
}
]]></programlisting>

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

        <para>
            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).
        </para>
    </sect2>
</sect1>
<!--
vim:se ts=4 sw=4 et:
-->
