<sect1 id="zend.controller.front">
    <title>O Front Controller</title>

    <sect2 id="zend.controller.front.overview">
        <title>Resumo</title>

        <para>
            <code>Zend_Controller_Front</code> implementa um <ulink
                url="http://www.martinfowler.com/eaaCatalog/frontController.html">padrão Front
                Controller</ulink> usado nas aplicações <ulink
                url="http://pt-br.wikipedia.org/wiki/Model-view-controller">Model-View-Controller
                (MVC)</ulink>. Seu objetivo é inicializar o ambiente de requisição,
                roterizar as requisições que chegam, e despachalas para quaquel ações
                descobertas; ele agrega alguma resposta e devolve-os quando o
                processo é completo.
        </para>

        <para>
            <code>Zend_Controller_Front</code> também implementa o <ulink
                url="http://pt-br.wikipedia.org/wiki/Singleton_pattern">padrão Singleton
            </ulink>, signicando que somente uma instancia dele pode estar disponivel
            em qualquer tempo. Isto permite que ele atue também como um registro em
            que outros objetos no processo de despacho possam usar.
        </para>

        <para>
            <code>Zend_Controller_Front</code> registra uma <link
                linkend="zend.controller.plugins">plugin de entrada</link> que
            por si só, permite que vários eventos sejam disparados para
            outros plugins observadores. Em muitos casos, isto permite ao
            desenvolvedor a oportunidade para mudar o processo de despacho do
            site sem a necessidade de extender o controlador de frente para
            adicionar funcionalidade.
        </para>

        <para>
            O mínimo necessário, que o controlador de frente necessita é um ou mais
            caminho para os diretórios contendo os
            <link linkend="zend.controller.action">controles de ação</link>
            para poder fazer seu trabalho. Vários metódos também
            podem ser invocados para mudar o ambiente do controlador de frente
            e suas classe auxiliares.
        </para>

        <note>
            <title>Comportamento padrão</title>
            <para>
                Por padrão, o controlador de frente carrega o <link
                    linkend="zend.controller.plugins.standard.errorhandler">ErrorHandler</link>
                plugin, bem como o  <link
                    linkend="zend.controller.actionhelpers.viewrenderer">ViewRenderer</link>
                plugin de ação auxiliar. Faz isto para simplificar o controle de erro e
                a apresentação de visulizadores em seus controles, repectivamente.
            </para>

            <para>
                Para desabilitar o <code>ErrorHandler</code>, execute a seguinte
                chamada em qualquer ponto antes de chamar <code>dispatch()</code>:
            </para>

            <programlisting role="php"><![CDATA[<?php
// Disable the ErrorHandler plugin:
$front->setParam('noErrorHandler', true);]]>
            </programlisting>

            <para>
                Para desabilitar o <code>ViewRenderer</code>, faça o seguinte
                antes de chamar <code>dispatch()</code>:
            </para>

            <programlisting role="php"><![CDATA[<?php
// Disable the ViewRenderer helper:
$front->setParam('noViewRenderer', true);]]>
            </programlisting>
        </note>
    </sect2>

    <sect2 id="zend.controller.front.methods.primary">
        <title>Metódos Primários</title>

        <para>
            O controlador de frente possuí vários acessores para configurar
            seu ambiente. Entretanto existem três metódos chaves primários
            da funcionalidades do controlador de frente:
        </para>

        <sect3 id="zend.controller.front.methods.primary.getinstance">
            <title>getInstance()</title>

            <para>
                <code>getInstance()</code> é usado para retirar a instancia
                do controlador de frente. Como o controlador de frente
                implementa o padrão Singleton, isto também é a unica
                maneira possível de instanciar um objeto controlador de frente.
            </para>

            <programlisting role="php"><![CDATA[<?php
$front = Zend_Controller_Front::getInstance();]]>
            </programlisting>
        </sect3>

        <sect3 id="zend.controller.front.methods.primary.setcontrollerdirectory">
            <title>setControllerDirectory() and addControllerDirectory</title>

            <para>
                <code>setControllerDirectory()</code> é usado para dizer <link
                    linkend="zend.controller.dispatcher">ao despachador</link>
                onde procurar os arquivos da classes dos <link
                    linkend="zend.controller.action">controladores de ação</link>.
                Ele aceita tanto um caminho único ou um array associativo
                com pares módulo/caminho.
            </para>

            <para>
                Alguns exemplos:
            </para>

            <programlisting role="php"><![CDATA[
// Set the default controller directory:
$front->setControllerDirectory('../application/controllers');

// Set several module directories at once:
$front->setControllerDirectory(array(
    'default' => '../application/controllers',
    'blog'    => '../modules/blog/controllers',
    'news'    => '../modules/news/controllers',
));

// Add a 'foo' module directory:
$front->addControllerDirectory('../modules/foo/controllers', 'foo');]]>
            </programlisting>

            <note>
                <para>
                    Se você usar <code>addControllerDirectory()</code>  sem um
                    nome de módulo, ele irá configurar o diretório para o módulo
                    <code>padrão</code> -- sobrescrevendo-o se ele já existir.
                </para>
            </note>

            <para>
                Você pode pegar a configuração corrente do diretório do
                controlador usando <code>getControllerDirectory()</code>;
                isto irá retornar um array de pares módulo/diretório.
            </para>
        </sect3>

        <sect3 id="zend.controller.front.methods.primary.dispatch">
            <title>dispatch()</title>

            <para>
                <code>dispatch(Zend_Controller_Request_Abstract $request = null,
                    Zend_Controller_Response_Abstract $response = null)</code>
                faz o trabalho pesado do controlador de frente. Ele pode
                opcionalmente pegar um <link linkend="zend.controller.request">objeto
                de requisição</link> e/ou um <link
                    linkend="zend.controller.response">objeto de resposta</link>,
                permitindo ao desenvolvedor passar a ele objetos personalizados
                de cada.
            </para>

            <para>
                Se nenhum objeto de requisição ou resposta for passado,
                <code>dispatch()</code> irá procurar por objetos previamente
                registrados e usa-los ou instanciar versões padrão para usar
                em seus processos (em ambos os casos, o HTTP será usado como padrão).
            </para>

            <para>
                Similarmente, <code>dispatch()</code> checa por uma
                <link linkend="zend.controller.router">router</link> registrada e
                um objetos de
                <link linkend="zend.controller.dispatcher">dispacho</link>,
                instanceando a versão padrão de cada um deles se não encontrar
                nenhum.
            </para>

            <para>
                O processo de dispacho possui três eventos distintos:
            </para>

            <itemizedlist>
                <listitem><para>Roterização</para></listitem>
                <listitem><para>Despacho</para></listitem>
                <listitem><para>Resposta</para></listitem>
            </itemizedlist>

            <para>
                A Roterização realiza-se exatamente uma vez, usando os valores
                no objeto de requisicão quando <code>dispatch()</code> é chamado.
                O Despacho ocorre em um laço; uma requisição pode tanto indicar
                multiplas ações para dispachar, ou o controlador ou um plugin pode
                reiniciar o objeto de requisição para forçar ações adicionais
                para o despacho. Quando tudo está pronto, o controlador de frente
                retorna uma resposta.
            </para>
        </sect3>

        <sect3 id="zend.controller.front.methods.primary.run">
            <title>run()</title>

            <para>
                <code>Zend_Controller_Front::run($path)</code> é um método estático
                que toma simplesmente um caminho para um diretório contendo
                os controladores. Ele

                <code>Zend_Controller_Front::run($path)</code> is a static
                method taking simply a path to a directory containing
                controllers. Ele traz um exemplo de controlador de frente (via
                <link
                    linkend="zend.controller.front.methods.primary.getinstance">getInstance()</link>,
                registra o caminho fornecido via <link
                    linkend="zend.controller.front.methods.primary.setcontrollerdirectory">setControllerDirectory()</link>,
                e finalmente <link
                    linkend="zend.controller.front.methods.primary.dispatch">dispacha</link>.
            </para>

            <para>
                Basicamente, <code>run()</code> é um método de conveniência que pode
                ser usado para configurações de sítios que não necessitam de customizações
                no ambiente de controle de frente.
            </para>

            <programlisting role="php"><![CDATA[<?php
// Instantiate front controller, set controller directory, and dispatch in one
// easy step:
Zend_Controller_Front::run('../application/controllers');]]>
            </programlisting>
        </sect3>
    </sect2>

    <sect2 id="zend.controller.front.methods.environment">
        <title>Métodos Acessores Ambientais</title>

        <para>
            Além dos métodos enumerados em cima, há um número de
            os métodos acessores que podem ser usados para afetar o ambiente
            do controlador de frente - e assim o ambiente das classes em que
            o controlador de frente delega.
        </para>

        <itemizedlist>
            <listitem>
                <para>
                    <code>resetInstance()</code> pode ser usado para limpar
                    todas as configurações atualmente definidas.
                    Seu propósito inicial é para teste, mas
                    ele também pode ser usado para intâncias onde você
                    deseja encadear um conjunto de múltiplos controladores de
                    frente.
                </para>
            </listitem>

            <listitem>
                <para>
                    <code>(set|get)DefaultControllerName()</code> permite a você
                    específicar um nome difetente para usar no controlador padrão
                    ('index' é usado de outra maneira) e recuperar o valor atual.
                    Eles apontaram para o <link
                        linkend="zend.controller.dispatcher">o despachante</link>.
                </para>
            </listitem>

            <listitem>
                <para>
                    <code>(set|get)DefaultActionName()</code> permite a você epecíficar
                    um nome diferente para ser usado na ação padrão ('index' é usado
                    por padrão) e recuperar o valor atual. Eles apontãm para
                    <link linkend="zend.controller.dispatcher"> o
                        despachante</link>.
                </para>
            </listitem>

            <listitem>
                <para>
                    <code>(set|get)Request()</code> permite a você específicar
                    a classe <link
                        linkend="zend.controller.request">de pedido</link>
                    ou objeto para usar durente o processo de despacho e
                    para recuperar o objeto atual. Ao configurar o objeto de
                    requisição, você pode passar uma nome de classe de requisição,
                    neste caso o metódo irá carregar o arquivo da classe e instancia-la.
                </para>
            </listitem>

            <listitem>
                <para>
                    <code>(set|get)Router()</code> permite a você especificar o objeto ou classe <link
                        linkend="zend.controller.router">roteador(a)</link>
                    para usar durante o processo de dispacho e para
                    recuperar o objeto atual. Quando estiver definindo o objeto
                    roteador, você pode passar o nome de uma classe roteadora
                    e neste caso o metódo roteado irá carregar o arquivo da classe
                    e instancia-la.
                </para>

                <para>
                    Quando recuperá o objeto roteador, ele primeiro verifica se já
                    existe um, se não, instanceia o reteador padrão (roteador re-escrito).
                </para>
            </listitem>

            <listitem>
                <para>
                    <code>(set|get)BaseUrl()</code> let you specify <link
                        linkend="zend.controller.request.http.baseurl">the base
                        URL</link> to strip when routing requests and to
                    retrieve the current value. The value is provided to the
                    request object just prior to routing.
                </para>
            </listitem>

            <listitem>
                <para>
                    <code>(set|get)Dispatcher()</code> let you specify <link
                        linkend="zend.controller.dispatcher">the
                        dispatcher</link> class or object to use during the
                    dispatch process and retrieve the current object. When
                    setting the dispatcher object, you may pass in a dispatcher
                    class name, in which case the method will load the class
                    file and instantiate it.
                </para>

                <para>
                    When retrieving the dispatcher object, it first checks to see if
                    one is present, and if not, instantiates the default
                    dispatcher.
                </para>
            </listitem>

            <listitem>
                <para>
                    <code>(set|get)Response()</code> let you specify <link
                        linkend="zend.controller.response">the response</link>
                    class or object to use during the dispatch process and to
                    retrieve the current object. When setting the response
                    object, you may pass in a response class name, in which case
                    the method will load the class file and instantiate it.
                </para>
            </listitem>

            <listitem>
                <para>
                    <code>registerPlugin(Zend_Controller_Plugin_Abstract $plugin, $stackIndex = null)</code>
                    allows you to register a <link
                        linkend="zend.controller.plugins">plugin objects</link>.
                    By setting the optional <code>$stackIndex</code>, you can
                    control the order in which plugins will execute.
                </para>
            </listitem>

            <listitem>
                <para>
                    <code>unregisterPlugin($plugin)</code> let you
                    unregister <link
                        linkend="zend.controller.plugins">plugin objects</link>.
                    <code>$plugin</code> may be either a plugin object or a
                    string denoting the class of plugin to unregister.
                </para>
            </listitem>

            <listitem>
                <para>
                    <code>throwExceptions($flag)</code> is used to turn on/off
                    the ability to throw exceptions during the dispatch process.
                    By default, exceptions are caught and placed in the <link
                        linkend="zend.controller.response">response
                        object</link>; turning on <code>throwExceptions()</code>
                    will override this behaviour.
                </para>

                <para>
                    For more information, read <xref
                        linkend="zend.controller.exceptions" />.
                </para>
            </listitem>

            <listitem>
                <para>
                    <code>returnResponse($flag)</code> is used to tell the front
                    controller whether to return the response
                    (<code>true</code>) from <code>dispatch()</code>, or if the
                    response should be automatically emitted
                    (<code>false</code>).  By default, the response is
                    automatically emitted (by calling
                    <code>Zend_Controller_Response_Abstract::sendResponse()</code>);
                    turning on <code>returnResponse()</code> will override this
                    behaviour.
                </para>

                <para>
                    Reasons to return the response include a desire to check for
                    exceptions prior to emitting the response, needing to log
                    various aspects of the response (such as headers), etc.
                </para>
            </listitem>
        </itemizedlist>
    </sect2>

    <sect2 id="zend.controller.front.methods.params">
        <title>Front Controller Parameters</title>

        <para>
            In the introduction, we indicated that the front controller also
            acts as a registry for the various controller components. It does so
            through a family of "param" methods. These methods allow you to
            register arbitrary data -- objects and variables -- with the front
            controller to be retrieved at any time in the dispatch chain. These
            values are passed on to the router, dispatcher, and action
            controllers. The methods include:
        </para>

        <itemizedlist>
            <listitem>
                <para>
                    <code>setParam($name, $value)</code> allows you to set a
                    single parameter of <code>$name</code> with value
                    <code>$value</code>.
                </para>
            </listitem>

            <listitem>
                <para>
                    <code>setParams(array $params)</code> allows you to set
                    multiple parameters at once using an associative array.
                </para>
            </listitem>

            <listitem>
                <para>
                    <code>getParam($name)</code> allows you to retrieve a single
                    parameter at a time, using <code>$name</code> as the
                    identifier.
                </para>
            </listitem>

            <listitem>
                <para>
                    <code>getParams()</code> allows you to retrieve the entire
                    list of parameters at once.
                </para>
            </listitem>

            <listitem>
                <para>
                    <code>clearParams()</code> allows you to clear a single
                    parameter (by passing a string identifier), multiple named
                    parameters (by passing an array of string identifiers), or the
                    entire parameter stack (by passing nothing).
                </para>
            </listitem>
        </itemizedlist>

        <para>
            There are several pre-defined parameters that may be set that have
            specific uses in the dispatch chain:
        </para>

        <itemizedlist>
            <listitem>
                <para>
                    <code>useDefaultControllerAlways</code> is used to hint to
                    <link linkend="zend.controller.dispatcher">the
                        dispatcher</link> to use the default controller in the
                    default module for any request that is not dispatchable
                    (i.e., the module, controller, and/or action do not exist).
                    By default, this is off.
                </para>

                <para>
                    See <xref linkend="zend.controller.exceptions.internal" />
                    for more detailed information on using this setting.
                </para>
            </listitem>

            <listitem>
                <para>
                    <code>disableOutputBuffering</code> is used to hint to <link
                        linkend="zend.controller.dispatcher">the
                        dispatcher</link> that it should not use output
                    buffering to capture output generated by action controllers.
                    By default, the dispatcher captures any output and appends
                    it to the response object body content.
                </para>
            </listitem>

            <listitem>
                <para>
                    <code>noViewRenderer</code> is used to disable the <link
                        linkend="zend.controller.actionhelpers.viewrenderer">ViewRenderer</link>.
                    Set this parameter to true to disable it.
                </para>
            </listitem>

            <listitem>
                <para>
                    <code>noErrorHandler</code> is used to disable the <link
                        linkend="zend.controller.plugins.standard.errorhandler">Error
                        Handler plugin</link>. Set this parameter to true to
                    disable it.
                </para>
            </listitem>
        </itemizedlist>
    </sect2>

    <sect2 id="zend.controller.front.subclassing">
        <title>Subclassing the Front Controller</title>

        <para>
            To subclass the Front Controller, at the very minimum you will need
            to override the <code>getInstance()</code> method:
        </para>

        <programlisting role="php"><![CDATA[
class My_Controller_Front extends Zend_Controller_Front
{
    public static function getInstance()
    {
        if (null === self::$_instance) {
            self::$_instance = new self();
        }

        return self::$_instance;
    }
}
]]>
        </programlisting>

        <para>
            Overriding the <code>getInstance()</code> method ensures that
            subsequent calls to
            <code>Zend_Controller_Front::getInstance()</code> will return an
            instance of your new subclass instead of a
            <code>Zend_Controller_Front</code> instance -- this is particularly
            useful for some of the alternate routers and view helpers.
        </para>

        <para>
            Typically, you will not need to subclass the front controller unless
            you need to add new functionality (for instance, a plugin
            autoloader, or a way to specify action helper paths). Some points
            where you may want to alter behaviour may include modifying how
            controller directories are stored, or what default router or
            dispatcher are used.
        </para>
    </sect2>
</sect1>
<!--
vim:se ts=4 sw=4 et:
-->
