Author: Andreia.Bellini
Date: 2010-01-22 03:24:44 +0100 (Fri, 22 Jan 2010)
New Revision: 27028
Added:
doc/branches/1.4/more-with-symfony/pt/10-Symfony-Internals.markdown
Log:
Portuguese translation
Added: doc/branches/1.4/more-with-symfony/pt/10-Symfony-Internals.markdown
===================================================================
--- doc/branches/1.4/more-with-symfony/pt/10-Symfony-Internals.markdown
(rev 0)
+++ doc/branches/1.4/more-with-symfony/pt/10-Symfony-Internals.markdown
2010-01-22 02:24:44 UTC (rev 27028)
@@ -0,0 +1,641 @@
+
+Funcionamento Interno do symfony
+=================
+
+*por Geoffrey Bachelet*
+
+Alguma vez você já se perguntou o que acontece com uma requisição HTTP quando
ela chega a uma
+aplicação symfony? Caso positivo, então você está no lugar certo. Este capítulo
+irá explicar em detalhes como o symfony processa cada requisição, a fim de
criar e
+retornar a resposta. Claro que, apenas descrever o processo faltaria um
+pouco de diversão, por isso vamos dar uma olhada em algumas coisas
interessantes que você pode fazer e
+onde você pode interagir neste processo.
+
+A Inicialização
+-------------
+
+Tudo começa no controlador de sua aplicação. Digamos que você tenha um
controlador `frontend`
+com um ambiente `dev` (um início clássico para qualquer projeto symfony)
+. Neste caso, você terá um *front controller* localizado em
+[`web/frontend_dev.php`](http://trac.symfony-project.org/browser/branches/1.3/lib/task/generator/skeleton/app/web/index.php).
+O que acontece exatamente nesse arquivo? Em apenas algumas linhas de código, o
symfony
+obtêm a configuração da aplicação e cria uma instância do
+`sfContext`, que é responsável por despachar a requisição. A configuração da
+aplicação é necessária para criar o objeto `sfContext`, que é
+o motor por trás do symfony e que depende da aplicação.
+
+>**TIP**
+>O symfony já lhe concede um pouco de controle no que acontece aqui permitindo
+>passar um diretório raiz personalizado para sua aplicação como o quarto
+>argumento de ~`ProjectConfiguration::getApplicationConfiguration()`~, bem como
+>uma classe de contexto personalizada como o terceiro (e último) argumento de
+>[`sfContext::createInstance()`](http://www.symfony-project.org/api/1_3/sfContext#method_createinstance)
+>(mas lembre-se que ela tem de estender `sfContext`).
+
+Obter a configuração da aplicação é um passo muito importante. Primeiro,
+o `sfProjectConfiguration` é responsável por descobrir
+a classe de configuração da aplicação, geralmente
`${application}Configuration`, localizada em
+`apps/${application}/config/${application}Configuration.class.php`.
+
+`sfApplicationConfiguration` na verdade estende `ProjectConfiguration`,
significando
+que qualquer método em `ProjectConfiguration` pode ser compartilhado entre
todas as aplicações.
+Isto significa também que `sfApplicationConfiguration` compartilha seu
construtor
+com ambos `ProjectConfiguration` e `sfProjectConfiguration`. Isto é
+ótimo, já que grande parte da configuração do projeto é realizada dentro
+do construtor de `sfProjectConfiguration`. Primeiro, vários valores úteis são
+calculados e armazenados, como, o diretório raiz do projeto e o diretório da
biblioteca do
+symfony. O `sfProjectConfiguration` também cria um novo distribuidor de
eventos (*event dispatcher*)
+do tipo `sfEventDispatcher`, a menos que um tenha sido passado como o quinto
+argumento de `ProjectConfiguration::getApplicationConfiguration()` no
+*front controller*.
+
+Só depois disso, você terá a oportunidade de interagir com o processo de
configuração
+sobrescrevendo o método `setup()` do `ProjectConfiguration`. Este
+geralmente é o melhor local para ativar / desativar plugins (usando
+[`sfProjectConfiguration::setPlugins()`](http://www.symfony-project.org/api/1_3/sfProjectConfiguration#method_setplugins),
+[`sfProjectConfiguration::enablePlugins()`](http://www.symfony-project.org/api/1_3/sfProjectConfiguration#method_enableplugins),
+[`sfProjectConfiguration::disablePlugins()`](http://www.symfony-project.org/api/1_3/sfProjectConfiguration#method_disableplugins)
ou
+[`sfProjectConfiguration::enableAllPluginsExcept()`](http://www.symfony-project.org/api/1_3/sfProjectConfiguration#method_enableallpluginsexcept)).
+
+Em seguida, os plugins são carregados por
[`sfProjectConfiguration::loadPlugins()`](http://www.symfony-project.org/api/1_3/sfProjectConfiguration#method_loadplugins)
+e o desenvolvedor tem uma chance de interagir com este processo através do
+[`sfProjectConfiguration::setupPlugins()`](http://www.symfony-project.org/api/1_3/sfProjectConfiguration#method_setupplugins)
que pode ser sobrescrito.
+
+A inicialização de um plugin é bastante simples. Para cada plugin,
+o symfony procura por uma classe `${plugin}Configuration` (por exemplo:
`sfGuardPluginConfiguration`)
+e, se for encontrado, cria uma instância dela. Caso contrário, a classe
`sfPluginConfigurationGeneric` é
+utilizada. Os seguintes métodos permitem modificar a configuração de um plugin:
+
+* `${plugin}Configuration::configure()`, antes do carregamento automático
(*autoloading*)
+* `${plugin}Configuration::initialize()`, após o carregamento automático
+
+Em seguida, `sfApplicationConfiguration` executa seu método `configure()`,
+que pode ser usado para personalizar a configuração de cada aplicação antes
+que comece o processo de inicialização da configuração interna em
+[`sfApplicationConfiguration::initConfiguration()`](http://www.symfony-project.org/api/1_3/sfApplicationConfiguration#method_initconfiguration).
+
+Esta parte do processo de configuração do symfony é responsável por muitas
coisas
+e existem diversos pontos de entrada caso você queira interagir nesse processo.
+Por exemplo, você pode interagir com a configuração do carregamento automático
(*autoloader*)
+conectando-se ao evento `autoload.filter_config`. Em seguida, vários
+arquivos de configuração importantes são carregados, incluindo o
`settings.yml` e o
+`app.yml`. Finalmente, um último pedaço da configuração do plugin está
disponível através do
+arquivo `config/config.php` de cada plugin ou do método da classe de
configuração `initialize()`.
+
+
+Se o `sf_check_lock` estiver ativado, o symfony irá buscar por um arquivo de
bloqueio (
+criado pela tarefa `project:disable`, por exemplo). Se o bloqueio for
encontrado,
+os seguintes arquivos são verificados e o primeiro disponível é incluído,
seguido
+imediatamente pela finalização do script:
+
+1. `apps/${application}/config/unavailable.php`,
+1. `config/unavailable.php`,
+1. `web/errors/unavailable.php`,
+1. `vendor/lib/symfony/lib/exception/data/unavailable.php`,
+
+Por último, o desenvolvedor tem uma última chance de personalizar a
inicialização da
+aplicação através do método ~`sfApplicationConfiguration::initialize()`~.
+
+### Resumo da inicialização e configuração
+
+* Recuperação da configuração da aplicação
+ * `ProjectConfiguration::setup()` (definir seus plugins aqui)
+ * Plugins são carregados
+ * `${plugin}Configuration::configure()`
+ * `${plugin}Configuration::initialize()`
+ * `ProjectConfiguration::setupPlugins()` (configurar seus plugins aqui)
+ * `${application}Configuration::configure()`
+ * `autoload.filter_config` é notificado
+ * Carregamento do `settings.yml` e `app.yml`
+ * `${application}Configuration::initialize()`
+* Criação de uma instância `sfContext`
+
+`sfContext` e *Factories*
+-------------------------
+
+Antes de mergulhar no processo de execução, vamos falar sobre uma parte vital
do
+workflow do symfony: as *factories*.
+
+No symfony, as *factories* são um conjunto de componentes ou classes que a sua
+aplicação depende. Exemplos de *factories* são `logger`, `i18n`, etc.
+Cada *factory* é configurada via `factories.yml`, que é compilada por um
+manipulador de configuração (*config handler*) (veremos sobre manipuladores de
configuração mais tarde) e convertidos em código PHP
+que realmente instancia os objetos *factory* (você pode ver este
+código em seu cache no
+arquivo `cache/frontend/dev/config/config_factories.yml.php`).
+
+>**NOTE**
+>O Carregamento da *Factory* acontece após a inicialização do `sfContext`.
Veja:
+>[`sfContext::initialize()`](http://www.symfony-project.org/api/1_3/sfContext#method_initialize)
+>e
[`sfContext::loadFactories()`](http://www.symfony-project.org/api/1_3/sfContext#method_loadfactories)
+>para mais informações.
+
+Neste ponto, você já pode personalizar uma grande parte do comportamento do
symfony
+apenas editando a configuração no `factories.yml`. Você pode até substituir as
classes
+*factory* internas do symfony pelas suas próprias!
+
+>**NOTE**
+>Se você estiver interessado em saber mais sobre as *factories*,
+>[O Livro de Referência do
symfony](http://www.symfony-project.org/reference/1_3/en/05-Factories)
+>bem como o arquivo
+>[`factories.yml`](http://trac.symfony-project.org/browser/branches/1.3/lib/config/config/factories.yml)
+>são recursos inestimáveis.
+
+Se você olhou o arquivo `config_factories.yml.php` gerado, você pode ter
+notado que as *factories* são instanciadas em uma determinada ordem. Essa
ordem é
+importante, pois algumas *factories* são dependentes de outras (por exemplo, o
+componente `routing` necessita, obviamente, do `request` para recuperar as
informações que
+ele precisa).
+
+Vamos falar em maiores detalhes sobre o `request`. Por padrão, a
+classe `sfWebRequest` representa o `request`. Após a criação da instância,
+[`sfWebRequest::initialize()`](http://www.symfony-project.org/api/1_3/sfWebRequest#method_initialize)
+é chamado, que reúne informações relevantes como os parâmetros GET / POST
+bem como o método HTTP. Você então tem a oportunidade de adicionar o seu
próprio
+processamento do pedido através do evento `request.filter_parameters`.
+
+### Usando o evento `request.filter_parameter`
+
+Imagine que o seu website disponibiliza uma API pública aos seus usuários. A
API
+está disponível através de HTTP, e cada usuário que deseja utilizá-la deve
fornecer uma chave de API
+válida através de um cabeçalho de solicitação (por exemplo `X_API_KEY`) que
será validada pela
+sua aplicação. Isso pode ser facilmente obtido utilizando o
+evento `request.filter_parameter`:
+
+ [php]
+ class apiConfiguration extends sfApplicationConfiguration
+ {
+ public function configure()
+ {
+ // ...
+
+ $this->dispatcher->connect('request.filter_parameters', array(
+ $this, 'requestFilterParameters'
+ ));
+ }
+
+ public function requestFilterParameters(sfEvent $event, $parameters)
+ {
+ $request = $event->getSubject();
+
+ $api_key = $request->getHttpHeader('X_API_KEY');
+
+ if (null === $api_key || false === $api_user =
Doctrine_Core::getTable('ApiUser')->findOneByToken($api_key))
+ {
+ throw new RuntimeException(sprintf('Invalid api key "%s"',
$api_key));
+ }
+
+ $request->setParameter('api_user', $api_user);
+
+ return $parameters;
+ }
+ }
+
+Você poderá então acessar seu usuário da API a partir do pedido (*request*):
+
+ [php]
+ public function executeFoobar(sfWebRequest $request)
+ {
+ $api_user = $request->getParameter('api_user');
+ }
+
+Esta técnica pode ser usada, por exemplo, para validar chamadas à webservices.
+
+>**NOTE**
+>O evento `request.filter_parameters` vem com muitas informações sobre
+>o pedido (*request*), consulte o método
+>[`sfWebRequest::getRequestContext()`](http://www.symfony-project.org/api/1_3/sfWebRequest#method_getrequestcontext)
+>para obter mais informações.
+
+A próxima *factory* muito importante é o roteamento (*routing*). A
inicialização de roteamento é
+bastante simples e consiste principalmente de coletar e configurar opções
específicas
+. Você pode, no entanto, interagir neste processo através do
+evento `routing.load_configuration`.
+
+>**NOTE**
+>O evento `routing.load_configuration` lhe fornece acesso a instância do
+>objeto de roteamento atual (por padrão,
+>[`sfPatternRouting`](http://trac.symfony-project.org/browser/branches/1.3/lib/routing/sfPatternRouting.class.php)).
+>Você pode então manipular rotas registradas através de uma variedade de
métodos.
+
+### Exemplo de uso do evento `routing.load_configuration`
+
+Por exemplo, você pode facilmente adicionar uma rota:
+
+ [php]
+ public function setup()
+ {
+ // ...
+
+ $this->dispatcher->connect('routing.load_configuration', array(
+ $this, 'listenToRoutingLoadConfiguration'
+ ));
+ }
+
+ public function listenToRoutingLoadConfiguration(sfEvent $event)
+ {
+ $routing = $event->getSubject();
+
+ if (!$routing->hasRouteName('my_route'))
+ {
+ $routing->prependRoute('my_route', new sfRoute(
+ '/my_route', array('module' => 'default', 'action' => 'foo')
+ ));
+ }
+ }
+
+O processamento da URL ocorre logo após a inicialização, através do método
+[`sfPatternRouting::parse()`](http://www.symfony-project.org/api/1_3/sfPatternRouting#method_parse).
+Existem alguns métodos envolvidos, mas tudo o que você precisa saber
+é que, quando chegamos ao final do método `parse()`, a rota correta foi
encontrada,
+instanciada e vinculada aos parâmetros relevantes.
+
+>**NOTE**
+>Para mais informações sobre roteamento, consulte o capítulo `Roteamento
Avançado` deste
+>livro.
+
+Uma vez que todas as *factories* tenham sido carregadas e configuradas
corretamente, o
+evento `context.load_factories` é disparado. Este evento é importante, pois
+é o primeiro evento no *framework* onde o desenvolvedor tem acesso a todos
+os objetos *factory* do núcleo do symfony (request, response, user, logging,
database,
+etc.).
+
+Este é também o momento para se conectar a um outro evento muito útil:
+`template.filter_parameters`. Este evento ocorre sempre que um arquivo é
processado pelo
+[`sfPHPView`](http://trac.symfony-project.org/browser/branches/1.3/lib/view/sfPHPView.class.php)
+e permite ao desenvolvedor controlar os parâmetros atualmente passados ao
*template*.
+`sfContext` aproveita este evento para adicionar alguns parâmetros úteis para
cada
+*template* (ou seja, `$sf_context`, `$sf_request`, `$sf_params`, `$sf_response`
+e `$sf_user`).
+
+Você pode se conectar ao evento `template.filter_parameters` a fim de
acrescentar
+parâmetros globais personalizados para todos os *templates*.
+
+### Aproveitando o evento `template.filter_parameters`
+
+Digamos que você decidiu que cada *template* utilizado deve ter acesso à um
+determinado objeto, digamos, um objeto *helper*. Neste caso, você pode
adicionar o seguinte
+código no `ProjectConfiguration`:
+
+ [php]
+ public function setup()
+ {
+ // ...
+
+ $this->dispatcher->connect('template.filter_parameters', array(
+ $this, 'templateFilterParameters'
+ ));
+ }
+
+ public function templateFilterParameters(sfEvent $event, $parameters)
+ {
+ $parameters['my_helper_object'] = new MyHelperObject();
+
+ return $parameters;
+ }
+
+Agora, cada *template* tem acesso a uma instância do `MyHelperObject` através
da variável
+`$my_helper_object`.
+
+### Resumo do `sfContext`
+
+1. Inicialização do `sfContext`
+1. Carregamento da *Factory*
+1. Eventos notificados:
+1.
[request.filter_parameters](http://www.symfony-project.org/reference/1_3/en/15-Events#chapter_15_sub_request_filter_parameters)
+1.
[routing.load_configuration](http://www.symfony-project.org/reference/1_3/en/15-Events#chapter_15_sub_routing_load_configuration)
+1.
[context.load_factories](http://www.symfony-project.org/reference/1_3/en/15-Events#chapter_15_sub_context_load_factories)
+1. Parâmetros globais dos *templates* adicionados
+
+Uma palavra sobre Manipuladores de Configuração (*Config Handlers*)
+-------------------------
+
+Os manipuladores de configuração são o coração do sistema de configuração do
symfony. Um manipulador
+de configuração é encarregado de *entender* o significado por trás de um
arquivo de
+configuração. Cada manipulador de configuração é simplesmente uma classe que é
usada para traduzir um conjunto de
+arquivos de configuração yaml em um bloco de código PHP que pode ser executado
quando
+necessário. Cada arquivo de configuração é atribuído à um manipulador de
configuração específico através do
+[arquivo
`config_handlers.yml`](http://trac.symfony-project.org/browser/branches/1.3/lib/config/config/config_handlers.yml).
+
+Para deixar claro, o trabalho de um manipulador de configuração *não* é de
fazer o processamento (*parse*) dos arquivos YAML
+(isto é realizado pelo `sfYaml`). Na verdade, o que os manipuladores de
configuração fazem é criar um conjunto
+de instruções PHP com base nas informações YAML e salvar as instruções
+em um arquivo PHP, que poderá ser eficientemente incluído posteriormente. A
versão *compilada*
+de cada arquivo de configuração YAML pode ser encontrada no diretório cache.
+
+O manipulador de configuração mais comumente utilizado é certamente o
+[`sfDefineEnvironmentConfigHandler`](http://trac.symfony-project.org/browser/branches/1.3/lib/config/sfDefineEnvironmentConfigHandler.class.php),
+que permite configurações específicas por ambiente.
+Esse manipulador de configuração tem o cuidado de buscar apenas as definições
de configuração
+do ambiente atual.
+
+Ainda não está convencido? Vamos explorar o
+[`sfFactoryConfigHandler`](http://trac.symfony-project.org/browser/branches/1.3/lib/config/sfFactoryConfigHandler.class.php).
+Este manipulador de configuração é usado para compilar o `factories.yml`, que
é um dos
+mais importantes arquivos de configuração do symfony. Esse manipulador de
configuração é muito
+especial, pois converte um arquivo de configuração YAML em código PHP que
+finalmente instancia as *factories* (todos os componentes importantes que
falamos
+anterioremente). Este manipulador é muito mais avançado que os outros, não é?
+
+Despachando e Executando o Pedido (*Request*)
+--------------------------------------------
+
+Já falamos o suficiente sobre *factories*, vamos voltar a explicação do
processo de despacho (*dispatch*) do pedido.
+Após o `sfContext` terminar a inicialização, o último passo é chamar o
+método `dispatch()` do controlador,
+[`sfFrontWebController::dispatch()`](http://www.symfony-project.org/api/1_3/sfFrontWebController#method_dispatch).
+
+O processo de despacho (*dispatch*) no symfony é muito simples. Na verdade,
+o `sfFrontWebController::dispatch()` simplesmente obtêm os nomes do módulo e
da ação
+dos parâmetros do pedido (*request*) e encaminha a aplicação através do
+[`sfController::forward()`](http://www.symfony-project.org/api/1_3/sfController#method_forward).
+
+>**NOTE**
+>Neste ponto, se o roteamento não pôde processar qualquer nome de módulo ou
ação
+>a partir da URL atual, um
+>[`sfError404Exception`](http://trac.symfony-project.org/browser/branches/1.3/lib/exception/sfError404Exception.class.php)
é
+>originado, que irá encaminhar o pedido para o módulo de manipulação do erro
404 (ver
+>[`sf_error_404_module` e
+>`sf_error_404_action`](http://www.symfony-project.org/reference/1_3/en/04-Settings#chapter_04_sub_error_404)).
+>Note que você pode originar uma exceção em qualquer lugar na sua aplicação
para
+>atingir esse efeito.
+
+O método `forward` é responsável por uma série de verificações prévias à
execução
+bem como preparar a configuração e dados para a ação a ser executada.
+
+Primeiro, o controlador verifica a presença de um arquivo
+[`generator.yml`](http://trac.symfony-project.org/browser/branches/1.3/lib/config/config/generator.yml)
+para o módulo atual. Esta verificação é realizada primeiro (depois de limpeza
básica no
+nome do módulo e da ação), pois o arquivo de configuração `generator.yml` (se
+existir) é responsável por gerar a classe base das ações para o módulo
+(através da seu
+[manipulador de configuração,
`sfGeneratorConfigHandler`](http://trac.symfony-project.org/browser/branches/1.3/lib/config/sfGeneratorConfigHandler.class.php)).
+Isso é necessário para a próxima etapa, que verifica se o módulo e a ação
+existem. Isto é delegado ao controlador, através de
+[`sfController::actionExists()`](http://www.symfony-project.org/api/1_3/sfController#method_actionexists),
+que, por sua vez, chama o método
+[`sfController::controllerExists()`](http://www.symfony-project.org/api/1_3/sfController#method_controllerexists)
+. Aqui, novamente, se o método `actionExists()` falhar, um
`sfError404Exception`
+é gerado.
+
+>**NOTE**
+>O
+>[`sfGeneratorConfigHandler`](http://trac.symfony-project.org/browser/branches/1.3/lib/config/sfGeneratorConfigHandler.class.php)
é
+>um manipulador de configuração especial que cuida de instanciar a classe
correta do gerador (*generator*)
+>para o seu módulo e executá-lo. Para mais informações sobre manipuladores de
configuração
+, ver *Uma palavra sobre manipuladores de configuração* neste capítulo.
+>Além disso, para obter mais informações sobre o `generator.yml`, veja o
+>[capítulo 6 do Livro de Referência do
symfony](http://www.symfony-project.org/reference/1_3/en/06-Admin-Generator).
+
+Não há muito que você pode fazer aqui além de sobrescrever o método
+[`sfApplicationConfiguration::getControllerDirs()`](http://www.symfony-project.org/api/1_3/sfApplicationConfiguration#method_getcontrollerdirs)
+na classe de configuração da aplicação. Esse método retorna um array
+de diretórios onde os arquivos dos controladores residem, com um parâmetro
adicional
+para dizer ao symfony se ele deve verificar se os controladores em cada
diretório estão
+ativados através da opção de configuração `sf_enabled_modules` no
`settings.yml`.
+Por exemplo, `getControllerDirs()` poderia parecer com o seguinte código:
+
+ [php]
+ /**
+ * Controladores em /tmp/myControllers não precisam ser ativados
+ *para serem detectados
+ */
+ public function getControllerDirs($moduleName)
+ {
+ return array_merge(parent::getControllerDirs($moduleName), array(
+ '/tmp/myControllers/'.$moduleName => false
+ ));
+ }
+
+>**NOTE**
+>Se a ação não existe, um `sfError404Exception` é acionado.
+
+O próximo passo é recuperar uma instância do controlador que contém a ação.
+Isso é tratado através do método
+[`sfController::getAction()`](http://www.symfony-project.org/api/1_3/sfController#method_getaction)
+que, como o `actionExists()`, é uma fachada para o método
+[`sfController::getController()`](http://www.symfony-project.org/api/1_3/sfController#method_getcontroller).
+Finalmente, a instância do controlador é adicionada na *action stack*.
+
+>**NOTE**
+>A *action stack* é uma pilha do estilo FIFO (*First In First Out*) que contém
todas as
+>ações executadas durante o pedido. Cada item dentro da pilha é representado
com
+> um objeto `sfActionStackEntry`. Você sempre pode acessar a pilha com
+>`sfContext::getInstance()->getActionStack()` ou
+>`$this->getController()->getActionStack()` a partir de uma ação.
+
+Após carregar mais um pouco de configuração, nós estaremos prontos para
executar a nossa ação.
+A configuração específica para o módulo ainda precisa ser carregada, ela pode
ser
+encontrada em dois locais distintos. Primeiro, o symfony procura o arquivo
`module.yml`
+(normalmente localizado em
`apps/frontend/modules/yourModule/config/module.yml`)
+que, por ser um arquivo de configuração YAML, usa o cache de configuração.
Além disso,
+este arquivo de configuração pode declarar o módulo como *interno*, utilizando
a
+configuração `mod_yourModule_is_internal` que fará o pedido falhar neste
+ponto já que um módulo interno não pode ser chamado publicamente.
+
+>**NOTE**
+>Módulos internos são utilizados para gerar conteúdo de e-mail (através do
+>`getPresentationFor()`, por exemplo). Agora você deve usar outras técnicas,
+>tais como o processamento parcial (`$this->renderPartial()`) em seu lugar.
+
+Agora que o `module.yml` foi carregado, é hora de verificar uma segunda vez se
o
+módulo atual está habilitado. Na verdade, você pode definir a configuração
`mod_$moduleName_enabled`
+para `false`, se você deseja desativar o módulo neste momento.
+
+>**NOTE**
+>Como mencionado, existem duas maneiras de ativar ou desativar um módulo.
+>A diferença é o que acontece quando o módulo é desativado. No primeiro caso,
+>quando a configuração `sf_enabled_modules` é verificada, um módulo
desabilitado fará
+>uma
+>[`sfConfigurationException`](http://trac.symfony-project.org/browser/branches/1.3/lib/exception/sfConfigurationException.class.php)
+>ser acionada. Deve ser usado quando deseja-se desativar um módulo de forma
permanente. No
+>segundo caso, através da configuração `mod_$moduleName_enabled`, um módulo
desativado
+>irá fazer a aplicação redirecionar para o módulo desabilitado (ver as
configurações [
+>`sf_module_disabled_module` e
+>`sf_module_disabled_action`](http://www.symfony-project.org/reference/1_3/en/04-Settings#chapter_04_sub_module_disabled)
+>). Você deve usar este quando deseja desativar um módulo temporariamente.
+
+A última oportunidade para configurar um módulo se encontra no arquivo
`config.php`
+(`apps/frontend/modules/yourModule/config/config.php`) onde você pode
adicionar
+código PHP arbitrário que será executado no contexto do método
+[`sfController::forward()`](http://www.symfony-project.org/api/1_3/sfController#method_forward)
+(ou seja, você tem acesso à instância `sfController` através da variável
`$this`,
+pois o código é literalmente executado dentro da classe `sfController`).
+
+### Resumo do Processo de Despacho do Pedido
+
+1.
[`sfFrontWebController::dispatch()`](http://www.symfony-project.org/api/1_3/sfFrontWebController#method_dispatch)
é chamado
+1.
[`sfController::forward()`](http://www.symfony-project.org/api/1_3/sfController#method_forward)
é chamado
+1. Verifica se há um 'generator.yml'
+1. Verifica se o módulo / ação existe
+1. Recupera uma lista dos diretórios dos controladores
+1. Obtêm uma instância da ação
+1. Carrega a configuração do módulo através do `module.yml` e/ou `config.php`
+
+A Cadeia de Filtros
+----------------
+
+Agora que toda a configuração foi realizada, é hora de iniciar o trabalho real.
+Trabalho real, neste caso específico, é a execução da cadeia de filtros.
+
+>**NOTE**
+>A cadeia de filtros do symfony implementa um padrão de *design* conhecido como
+[*chain of responsibility*]
(http://en.wikipedia.org/wiki/Chain-of-responsibility_pattern).
+>É um padrão simples, mas poderoso, que permite ações encadeadas, onde cada
+>parte da cadeia é capaz de decidir se deve ou não continuar a
+>execução.
+>Cada parte da cadeia também é capaz de executar tanto antes como depois do
+>resto das partes da cadeia.
+
+A configuração da cadeia de filtro é obtida a partir do arquivo
+[`filters.yml`](http://trac.symfony-project.org/browser/branches/1.3/lib/config/config/filters.yml)
do módulo atual,
+razão pela qual a instância da ação é necessária. Esta é sua chance de
modificar o
+conjunto de filtros executados pela cadeia. Basta lembrar que o filtro
`rendering`
+deve ser sempre o primeiro na lista (veremos porque mais tarde). A
configuração padrão
+dos filtros é a seguinte:
+
+*
[`rendering`](http://trac.symfony-project.org/browser/branches/1.3/lib/filter/sfRenderingFilter.class.php)
+*
[`security`](http://trac.symfony-project.org/browser/branches/1.3/lib/filter/sfSecurityFilter.class.php)
+*
[`cache`](http://trac.symfony-project.org/browser/branches/1.3/lib/filter/sfCacheFilter.class.php)
+*
[`execution`](http://trac.symfony-project.org/browser/branches/1.3/lib/filter/sfExecutionFilter.class.php)
+
+>**NOTE**
+>É altamente recomendável adicionar seus próprios filtros entre o filtro
+>`security` e o `cache`
+
+### O Filtro `security`
+
+Uma vez que o filtro `rendering` espera por todos os outros filtros terminarem
antes de fazer qualquer coisa, o
+primeiro filtro que realmente executa é o filtro `security`. Este filtro
+garante que tudo está certo de acordo com o arquivo de configuração
+[`security.yml`](http://trac.symfony-project.org/browser/branches/1.3/lib/config/config/security.yml)
+. Especificamente, o filtro encaminha um usuário não autenticado
+ao módulo e ação `login` e um usuário com credenciais insuficientes para
+o módulo / ação `secure`. Note que este filtro só é executado se
+a segurança está habilitada para a determinada ação.
+
+### O Filtro `cache`
+
+Em seguida vem o filtro `cache`. Este filtro tira vantagem da sua capacidade de
+evitar que filtros adicionais sejam executados. Na verdade, se o cache estiver
ativado,
+e se a página solicitada pelo usuário estiver no cache, a ação não é
executada. Evidentemente, isso
+irá funcionar apenas para uma página totalmente em cache, que não é o caso da
maioria
+das páginas.
+
+Mas esse filtro tem um segundo pedaço de lógica que é executado após o
+filtro `execution`, e pouco antes do filtro `rendering`. Este código é
+responsável pela criação dos cabeçalhos HTTP de cache corretos, e de adicionar
a página
+no cache, se necessário, graças ao método
+[`sfViewCacheManager::setPageCache()`](http://www.symfony-project.org/api/1_3/sfViewCacheManager#method_setpagecache).
+
+
+### O Filtro `execution`
+
+O último filtro, mas não menos importante, é o filtro `execution` que irá,
finalmente, cuidar de
+executar a sua lógica de negócio e a manipulação da visão associada.
+
+Tudo começa quando o filtro verifica o cache para a ação atual.
+Naturalmente, se temos algo no cache, a execução da ação atual é
+ignorada e a visão `Success` é então executada.
+
+Se a ação não for encontrada no cache, então é hora de executar a
+lógica do controlador `preExecute()`, e, finalmente, executar a ação
+. Isto é realizado pela instância da ação através da chamada do
+[`sfActions::execute()`](http://www.symfony-project.org/api/1_3/sfActions#method_execute).
+Este método não faz muito: ele simplesmente verifica se é possível executar a
ação, e, então,
+a executa. Voltando ao filtro, a lógica da ação `postExecute()` é agora
executada.
+
+>**NOTE**
+>O valor de retorno de sua ação é muito importante, uma vez que irá determinar
+>que visão será executada. Por padrão, se nenhum valor de retorno é encontrado,
+>é assumido o `sfView::SUCCESS` (que se traduz, você adivinhou, em `Success`,
como em
+>`indexSuccess.php`).
+
+Seguindo com o processo, agora está na hora da visão. O filtro verifica por
dois valores de retorno especiais
+que a sua ação pode ter retornado, `sfView::HEADER_ONLY`
+e `sfView::NONE`. Cada um faz exatamente o que o seu nome sugere: envia apenas
cabeçalhos HTTP
+(internamente tratado através do
+[`sfWebResponse::setHeaderOnly()`](http://www.symfony-project.org/api/1_3/sfWebResponse#method_setheaderonly))
+e não exibe nenhuma página.
+
+>**NOTE**
+>Os nomes internos disponíveis para a visão são: `ALERT`, `ERROR`, `INPUT`,
`NONE` e `SUCCESS`. Mas você pode
+>basicamente retornar o que quiser.
+
+Uma vez que sabemos que *vamos* exibir alguma coisa, nós estamos prontos para
entrar na
+etapa final do filtro: a execução de visão atual.
+
+A primeira coisa que fazemos é recuperar um objeto
[`sfView`](http://trac.symfony-project.org/browser/branches/1.3/lib/view/sfView.class.php)
+através do método
[`sfController::getView()`](http://www.symfony-project.org/api/1_3/sfController#method_getview).
Este objeto pode vir de
+dois lugares diferentes. Primeiro, você poderia ter um objeto de exibição
personalizado para esta ação específica
+(assumindo que o módulo/ação atual é, vamos manter simples,
+módulo/ação) `actionSuccessView` ou `module_actionSuccessView` em um arquivo
+chamado `apps/frontend/modules/module/view/actionSuccessView.class.php`.
+Caso contrário, a classe definida na configuração `mod_module_view_class`
+será usada. O valor padrão desta opção é
[`sfPHPView`](http://trac.symfony-project.org/browser/branches/1.3/lib/view/sfPHPView.class.php).
+
+>**TIP**
+>Usando a sua própria classe de visão você tem a oportunidade de executar
alguma lógica de visão específica,
+>através do método
[`sfView::execute()`](http://www.symfony-project.org/api/1_3/sfView#method_execute)
+>. Por exemplo, você pode instanciar a sua própria *template engine*.
+
+Existem três modos de renderização possível para executar a visão:
+
+1. `sfView::RENDER_NONE`: equivalente a `sfView::NONE`, anula qualquer
renderização de ser executada.
+1. `sfView::RENDER_VAR`: preenche a apresentação da ação, que depois pode ser
acessada através do método
[`sfActionStackEntry::getPresentation()`](http://www.symfony-project.org/api/1_3/sfActionStackEntry#method_getpresentation).
+1. `sfView::RENDER_CLIENT`, o modo padrão, irá processar a visão e incluir o
conteúdo da resposta.
+
+>**NOTE**
+>Na verdade, o modo de processamento é utilizado apenas através do método
+>[`sfController::getPresentationFor()`](http://www.symfony-project.org/api/1_3/sfController#method_getpresentationfor)
que retorna o processamento para um
+>determinado módulo/ação.
+
+### O Filtro `rendering`
+
+Estamos quase terminando agora, apenas um último passo. A cadeia de filtro
quase
+terminou a execução, mas você se lembra do filtro `rendering`? Ele está
aguardando
+desde o início da cadeia, que todos os filtros concluam o seu trabalho para
que ele possa
+fazer o seu próprio. Ou seja, o filtro `rendering` envia o conteúdo da
resposta para o navegador, usando
+[`sfWebResponse::send()`](http://www.symfony-project.org/api/1_3/sfWebResponse#method_send).
+
+### Resumo da execução da cadeida de filtros
+
+1. A cadeia de filtros é instanciada com a configuração do arquivo
`filters.yml`
+1. O filtro `security` verifica as autorizações e credenciais
+1. O filtro `cache` manipula o cache para a página atual
+1. O filtro `execution` executa a ação
+1. O filtro `rendering` envia a resposta através do `sfWebResponse`
+
+Resumo Global
+--------------
+
+1. Obtenção da configuração da aplicação
+1. Criação de uma instância do `sfContext`
+1. Inicialização do `sfContext`
+1. Carregamento das *Factories*
+1. Eventos notificados:
+1. ~`request.filter_parameters`~
+1. ~`routing.load_configuration`~
+1. ~`context.load_factories`~
+1. Adicionados os parâmetros dos *templates* globais
+1.
[`sfFrontWebController::dispatch()`](http://www.symfony-project.org/api/1_3/sfFrontWebController#method_dispatch)
é chamado
+1.
[`sfController::forward()`](http://www.symfony-project.org/api/1_3/sfController#method_forward)
é chamado
+1. Verifica se existe um `generator.yml`
+1. Verifique se o módulo/ação existe
+1. Recupera uma lista de diretórios dos controladores
+1. Obtêm uma instância da ação
+1. Carrega a configuração do módulo através do `module.yml` e/ou `config.php`
+1. A cadeia de filtros é instanciada com a configuração do arquivo
`filters.yml`
+1. O filtro `security` verifica as autorizações e credenciais
+1. O filtro `cache` manipula o cache para a página atual
+1. O filtro `execution` executa a ação
+1. O filtro `rendering` envia a resposta através do `sfWebResponse`
+
+Reflexões finais
+--------------
+
+É isto! A requisição (*request*) foi tratada e agora estamos prontos para
processar a próxima.
+Naturalmente, poderíamos escrever um livro inteiro sobre os processos internos
do symfony, então
+este capítulo serve apenas como uma visão geral. Você é mais do que bem-vindo
para explorar
+os códigos-fonte você mesmo - que é, e sempre será, a melhor maneira de
aprender o
+funcionamento interno de qualquer *framework* ou biblioteca.
\ No newline at end of file
--
You received this message because you are subscribed to the Google Groups
"symfony SVN" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/symfony-svn?hl=en.