Documentação do Symfony
Renderizada do repositório symfony-docs-pt-BR no Github
single: Bastidores
Parece que você quer entender como funciona o Symfony2 e como extendê-lo. Isso me deixa muito feliz! Esta seção explica detalhadamente os bastidores do Symfony2.
Note
Você precisa ler esta seção apenas se quer entender como o Symfony2 funciona seu miolo, ou se quer extendê-lo.
O código do Symfony2 é feito de várias camadas independentes. Cada camada é construída em cima da anterior.
Tip
O Autoloading não é gerenciado diretamente pelo framework; isso é feito usando
o autoloader do Composer (vendor/autoload.php
), que é incluído no arquivo
app/autoload.php
.
HttpFoundation
¶O nível mais profundo é o componente HttpFoundation
.
HttpFoundation fornece os principais objetos necessários para lidar com HTTP.
É um objeto que abstrai algumas funções nativas do PHP e variáveis:
Request
abstrai as principais
variáveis globais do PHP como: $_GET
, $_POST
, $_COOKIE
,
$_FILES
, e $_SERVER
;Response
abstrai algumas
funções do PHP como: header()
, setcookie()
, e echo
;Session
e a interface
SessionStorageInterface
abstraem o gerenciamento da sessão, com uso das funções session_*()
.Note
Leia mais sobre o Componente HttpFoundation.
HttpKernel
¶No topo do HttpFoundation está o componente HttpKernel
.
HttpKernel manuseia a parte dinâmica do HTTP; é um sutíl que envolve as classes
Request e Response para padronizar as formas como as requisições são manipuladas. Ele
também oferece pontos de extensão e ferramentas ideais para criar um framework Web
sem muito trabalho.
Também, opcionalmente, adiciona conigurabilidade e extensibilidade, obrigado ao componente de Injeção de Dependência e um poderoso sistema de plugins (bundles).
See also
Leia mais sobre o Componente HttpKernel, Dependency Injection e Bundles.
FrameworkBundle
¶O bundle FrameworkBundle
é um pacote que amarra os
principais componentes e bibliotecas para fazer um leve e rápido framework MVC. Ele
vem com uma configuração padrão e convenções para facilitar a curva de aprendizado.
single: Bastidores; Kernel
A classe HttpKernel
é a classe central
do Symfony2 e é responsável por tratar os peedidos do cliente. Seu principal objetivo
é “converter” um objeto Request
para um
objeto Response
.
Cada Kernel do Symfony2 implementa
HttpKernelInterface
:
function handle(Request $request, $type = self::MASTER_REQUEST, $catch = true)
single: Bastidores; Resolvedor do Controlador
Para converter um Request para um Response, o Kernel se baseia em um “Controlador”. Um Controlador pode ser qualquer código PHP válido.
O Controlador deve ser uma implementação de
ControllerResolverInterface
:
public function getController(Request $request);
public function getArguments(Request $request, $controller);
e o Kernel poderá executá-lo.
O método
getController()
retorna o Controlador (um código PHP) associado com o dado Request. A implementação padrão
(ControllerResolver
) procura
pelo atributo _controller
do pedido que representa o nome do controlador
(uma string “classs::método”, como Bundle\BlogBundle\PostController:indexAction
).
Tip
A implementação padrão utiliza o
RouterListener
para definir o atributo _controller
do Request (veja Evento kernel.request).
O método
getArguments()
retorna um arrau de argumentos para passar para o Controlador. A implementação padrão
automaticamente resolve os argumentos dos métodos, baseado nos atributos do Request.
atributos do Request
Para cada argumento, o Symfony2 tenta pegar o valor do atributo do Request com o mesmo nome. Se este não estiver definido, o valor do argumento padrão é usado se definido:
// Symfony2 vai olhar para um atributo 'id' (obrigatório) // e um 'admin' (opcional) public function showAction($id, $admin = true) { // ... }
single: Bastidores; Trantando os Requests
O método handle()
pega um
Request
e sempre retorna um Response
. Para converter o Request
,
o handle()
depende do Resolver e uma cadeia ordenada de notificações de eventos
(veja a próxima seção para mais informações sobre cada Event):
kernel.request
é notificado – se um dos
listeners retorna um Response
, pula diretamente para o passo 8;kernel.controller
podem manipular o Controlador
chamado como queiram (alterá-lo, envolvê-lo, ...);Response
, os listeners do evento
kernel.view
podem converter o valor de retorno do Controlador para um Response
;kernel.response
podem manipular o Response
(conteúdo e cabeçalho);Se uma Exception é lançada durante o processamento, o kernel.exception
é notificado
e os listeners têm a oportundade de converter a Exception em um Response. Se isso
funcionar, o evento kernel.reponse
é notificado; se não, a Exception é relançada.
Se você não quer ser pego por uma Exception (para pedidos embutido por exemplo),
desabilite o evento kernel.exception
pasando false
como o terceiro argumento
do método handle()
.
single: Bastidores; Requests Internos
A qualquer momento durante o tratamento de um pedido (o ‘master’), um sub-pedido
pode ser manipulado. Você pode passar o tipo do pedido para o método handle()
(segundo argumento):
HttpKernelInterface::MASTER_REQUEST
;HttpKernelInterface::SUB_REQUEST
.O tipo é passado para todos os eventos e os listeners podem agir de acordo (alguns processamentos só devem ocorrer no pedido principal).
pair: Kernel; Evento
Cada evento acionado pelo Kernel é uma subclasse do
KernelEvent
. Isto significa que cada
evento tem acesso para a mesma informação básica:
getRequestType()
- retorna o tipo do pedido (HttpKernelInterface::MASTER_REQUEST
ou HttpKernelInterface::SUB_REQUEST
);getKernel()
- retorna o Kernel manipulando o pedido;getRequest()
- retorna o Request
sendo manipulado.getRequestType()
¶O método getRequestType()
permite os listeners para a saber o tipo do pedido.
Por exemple, se um listener só deve estar ativo para um pedidos principais, adicione
o seguinte código no início do seu método listener:
use Symfony\Component\HttpKernel\HttpKernelInterface;
if (HttpKernelInterface::MASTER_REQUEST !== $event->getRequestType()) {
// return immediately
return;
}
Tip
Se você ainda não está familiarizado com o Dispatcher de Evento do Symfony2, leia primeiro seção Documentação do Compoenente Dispatcher de Evento .
single: Evento; kernel.request
kernel.request
¶Classe do Evento: GetResponseEvent
O objetivo deste evento é retornar um objeto Response
ou variáveis de configuração
de um Controlador podem ser chamadas depois do evento. Qualquer listener pode returnar
um objeto Reponse
através do métod setResponse()
no evento. Neste caso, todos
os outros listeners não serão chamados.
Este evento é usado pelo FrameworkBundle
para popular o _controller
do atributo
do Request
, através do
RouterListener
. RequestListener
usa um objeto RouterInterface
para combinar o
Request
e determinar o nome do Controlador (armazenado no atributo _controller
do Request
).
See also
Leia mais em evento kernel.request.
single: Evento; kernel.controller
kernel.controller
¶Classe do Evento: FilterControllerEvent
Este evento não é usado pelo FrameworkBundle
, mas pode ser ponto de entrada usado
para modificar o controlador que será executado:
use Symfony\Component\HttpKernel\Event\FilterControllerEvent;
public function onKernelController(FilterControllerEvent $event)
{
$controller = $event->getController();
// ...
// o controlador pode ser trocado por qualquer código PHP válido
$event->setController($controller);
}
See also
Leio mais em evento kernel.controller.
single: Evento; kernel.view
kernel.view
¶Classe do Evento: GetResponseForControllerResultEvent
Este evento não é usado pelo FrameworkBundle
, mas pode ser usado para implementar
um sub-sistema de view. Este evento é chamado apenas se o Controlador não retornar
um objeto Response
. A proposta deste evento é permitir que qualquer outro valor possa
ser convertido em um Response
.
O valor retornado pelo Controlador é acessível através do método getControllerResult
:
use Symfony\Component\HttpKernel\Event\GetResponseForControllerResultEvent;
use Symfony\Component\HttpFoundation\Response;
public function onKernelView(GetResponseForControllerResultEvent $event)
{
$val = $event->getControllerResult();
$response = new Response();
// ... uma maneria de customizar o Response a partir de um valor de retorno
$event->setResponse($response);
}
See also
Leio mais no evento kernel.view.
single: Evento; kernel.response
kernel.response
¶Classe do Evento: FilterResponseEvent
A proposta deste evento é permitir outros sistemas de modificar ou substituir o objeto
Response
depois de criado:
public function onKernelResponse(FilterResponseEvent $event)
{
$response = $event->getResponse();
// ... modifique o objeto response
}
O``FrameworkBundle`` registra vários listeners:
ProfilerListener
:
coleta dados para o pedido atual;WebDebugToolbarListener
:
injeta a Web Debug Toolbar;ResponseListener
: fixes the
Responde Content-Type
baseado no formato do pedido;EsiListener
: adds a
Cabeçalho HTTP Surrogate-Control
quando o Response precisa ser transformado para
tags ESI.See also
Leia mais no evento kernel.response.
single: Evento; kernel.terminate
kernel.terminate
¶O objetivo deste evento é relizar tarefas mais “pesadas” depois que a resposta foi entregue ao cliente.
See also
Leia mais em evento kernel.terminate.
single: Evento; kernel.exception
kernel.exception
¶Classe de Evento: GetResponseForExceptionEvent
FrameworkBundle
registra um
ExceptionListener
que encaminha
o Request
para um dado Controlador (o valor do parâmetro
exception_listener.controller
– deve ser uma notação class::method
).
Um listener deste evento pode criar e definir um objeto Response
, criar e definir
um novo objeto Exception
, ou fazer nada:
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
use Symfony\Component\HttpFoundation\Response;
public function onKernelException(GetResponseForExceptionEvent $event)
{
$exception = $event->getException();
$response = new Response();
// configura o objeto Response baseado na exception capturada
$event->setResponse($response);
// você também pode definir uma nova Exception
// $exception = new \Exception('Some special exception');
// $event->setException($exception);
}
Note
Como o Symfony garante que o código do status do Response é como o mais adequado
dependendo da exceção, não vai funciona se definir o status na resposta. Se você
quiser substituir o código do status (você não deve fazer sem uma boa razão), defina
o X-Status-Code
no cabeçalho:
return new Response(
'Error',
404 // ignored,
array('X-Status-Code' => 200)
);
single: Dispatcher de Evento
O dispatcher de evento é um componente autônomo que é responsável por grande parte da lógica subjacente e do fluxo por trás de um pedido Symfony. Para mais informações, veja a
Documentação do Componente Dispatcher de Evento.
See also
Leia mais no evento kernel.exception.
single: Profiler
Quando ativado, o profiler do Symfony2 coleta informações úteis sobre cada pedido feito à sua aplicação e armazenadas para uma análise posterior. Utilize o profiler no ambiente de desenvolvimento para ajudar a depurar seu código e melhorar o desempenho; utilize-o em produção para problemas quando acontecerem.
Você raramente precisa lidar com o profiler diretamente, como o Symfony2 oferece ferramentas como Web Debug Toolbar e o Web Profiler. Se você utilizar o Symfony2 Standard Edition, o profiler, o web debug toolbar, e o web profiler estão configurados com configurações razoáveis.
Note
O profiler coleta informações sobre todo os pedidos (pedidos simples, redirecionamentos, exeçõec, pedidos Ajax, pedidos ESI; e para todos os métodos HTTP e todos formatos). Isso significa que para uma única URL, você pode ter vários dados de perfis associados (por pedido externo/resposta)
single: Profiler; Visualizando
No ambiente de desenvolvimento, a web debug toolbar está dispinível na parte de inferior de todas as páginas. Ela mostra um bom resumo do dados coletados e dá acesso instantâneo a uma grande quantidade de informações úteis quando algo não funciona como o esperado.
Se o resumo oferecido pela Web Debug Toolbar não é suficiente, clique no link do token (uma string feita de 13 caractéres randômicos) para acessar o Web Profiler.
Note
Se o token não está clicável, isso significa que a rota do profiler não está registrada (veja abaixo para obter informações de configuração)
O Web Profiler é uma ferramenta de visualização de dados que você pode usar no desenvolvimento para depurar seu código e melhor o desempenho; mas pode também ser usado para explorar problemas que ocorrem em produção. Ele expõe toda informação coletada pelo profiler na interface web.
single: Profiler; Usando o serviço do profiler
Você não precisa usar o visualizador padrão para acessar as informações coletadas. Mas
como você pode recuperar informações para um pedido específico? Quando o profiler armazena
os dados de um Request, também associa um token para ele; este token está disponível no
cabeçalho HTTP X-Debug-Token
do Response:
$profile = $container->get('profiler')->loadProfileFromResponse($response);
$profile = $container->get('profiler')->loadProfile($token);
Tip
Quando o profiler está ativado man não a web debug toolbar, ou quando você precisa
pegar o token para um pedido Aja, utilize uma ferramenta como o Firebug para pegar
o valor do cabeçalho HTTP X-Debug-Token
.
Utilize o método find()
para acessar os tokens baseados em alguns critérios:
// pega os 10 últimos tokens
$tokens = $container->get('profiler')->find('', '', 10);
// pegue os 10 últimos tokens para todas URLs que contenham /admin/
$tokens = $container->get('profiler')->find('', '/admin/', 10);
// pegue os 10 últimos tokens para pedidos locais
$tokens = $container->get('profiler')->find('127.0.0.1', '', 10);
Se você precisa manipular os dados coletados em uma máquina diferente da em que os dados
foram gerados, utilize os métodos
export()
e
import()
:
// na máquina de produção
$profile = $container->get('profiler')->loadProfile($token);
$data = $profiler->export($profile);
// na máquina de desenvolvimento
$profiler->import($data);
single: Profiler; Visualizando
A configuração padrão do Symfony2 vem com definições razoáveis para o profiler, a web debug toolbar, e o web profiler. Aqui está um exemplo de configuração para o ambiente de desenvolvimento:
# carrega o profiler
framework:
profiler: { only_exceptions: false }
# ativa o web profiler
web_profiler:
toolbar: true
intercept_redirects: true
<?xml version="1.0" encoding="UTF-8" ?>
<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:webprofiler="http://symfony.com/schema/dic/webprofiler"
xmlns:framework="http://symfony.com/schema/dic/symfony"
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd
http://symfony.com/schema/dic/webprofiler http://symfony.com/schema/dic/webprofiler/webprofiler-1.0.xsd
http://symfony.com/schema/dic/symfony http://symfony.com/schema/dic/symfony/symfony-1.0.xsd">
<!-- load the profiler -->
<framework:config>
<framework:profiler only-exceptions="false" />
</framework:config>
<!-- enable the web profiler -->
<webprofiler:config
toolbar="true"
intercept-redirects="true"
verbose="true"
/>
</container>
// carrega o profiler
$container->loadFromExtension('framework', array(
'profiler' => array('only-exceptions' => false),
));
// ativa o web profiler
$container->loadFromExtension('web_profiler', array(
'toolbar' => true,
'intercept-redirects' => true,
));
Quando only-execptions
está definida como true
, o profiler apenas coleta dados
quando uma exception é lançada pela aplicação.
Quando intercept-redirects
é definido como true
, o web profiler intercepta os
redirecionamentos e dá a você a oportunidade de ver os dados coletados antes de seguir
o redirecionamento.
Se você ativa o web profiler, você também precisa montar as rotas do profiler:
_profiler:
resource: @WebProfilerBundle/Resources/config/routing/profiler.xml
prefix: /_profiler
<?xml version="1.0" encoding="UTF-8" ?>
<routes xmlns="http://symfony.com/schema/routing"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/routing
http://symfony.com/schema/routing/routing-1.0.xsd">
<import
resource="@WebProfilerBundle/Resources/config/routing/profiler.xml"
prefix="/_profiler"
/>
</routes>
$collection->addCollection(
$loader->import(
"@WebProfilerBundle/Resources/config/routing/profiler.xml"
),
'/_profiler'
);
Como o profiler adiciona alguma sobrecarga, você pode querer ativar apenas em algumas
circunstâncias no ambiente de desenvolvimento. O parâmetro only-exceptions
limita
para 500 páginas, mas se quiser obter informações quando um IP do cliente vier de um
endereço específico, ou de uma parte limitada do site? Você pode usar um Profiler
Matcher, aprenda mais sobre ele no “/cookbook/profiler/matchers”.