quarta-feira, 2 de julho de 2014

Middlewares


Dia! Firm e Fort? Vamos lá! Agora vamos aprofundar um pouco mais. No Silex é permitido executar um comportamento que altera o seu padrão em diferentes estágios do tratamento na sua chamada através de Middlewares. As aplicações Middlewares são acionados de forma independente do pedido tratado e suas rotas são acionados quando sua associado é correspondido. Entendeu? É mais simples que parece, vou tentar explicar na prática que é mais divertido (deixando claro que vou usar como base sempre as documentações oficiais).

Aplicações Middlewares

Os Middlewares são executados apenas para o Request mestre.

Before Middleware

Um Before Middleware permite que você ajustar a solicitação ANTES que o controlador é executado:
$app->before(function (Request $request) {
    // seu código
});
Por padrão, o middleware é executado após o encaminhamento e a segurança.

Agora se você quiser que seu middleware seja executado mesmo se uma exceção é lançada no início (em um erro 404 ou 403, por exemplo) você precisa registrá-lo como um evento "Early" (precoce):
$app->before(function (Request $request) {
    // seu código
}, Application::EARLY_EVENT);
É claro que, neste caso, o encaminhamento e a segurança não serão executadas, e assim você não terá acesso ao local, a rota atual, ou segurança do usuário.

After Middleware

Permite ajustar a resposta antes de ser enviado para o cliente, ou seja, você ajusta as solicitações DEPOIS de tudo executado na aplicação.
$app->after(function (Request $request, Response $response) {
    // seu código
});

Finish Middleware

Permite que você execute tarefas após a resposta foi enviada para o cliente (como o envio de e-mails ou de registro):
$app->finish(function (Request $request, Response $response) {
    // seu código
    // Aviso: modificações no Request ou Response serão ignorados
});


Route Middlewares

As "Route Middlewares" são adicionados às rotas ou coleções de rotas na sua chamada/rota e elas só são acionados quando a sua rota correspondente é correspondida. Você também pode empilhá-los, entenderam? Difícil explicar mas é assim óh:
$antes = function(Request $request, Application $app) {
    // seu código
};
$depois = function(Request $request, Response $response, Application $app) {
    // seu código
};
$app->get('/sua_rota', function () {
   // seu código
})
  ->before($antes1)
  ->before($antes2)
  ->after($depois1)
  ->after($depois2);
Uma Before Route Middleware é executada antes da rota ser chamada, mas depois da Before Application Middlewares e uma After Route Middleware é executada depois da rota chamada, mas antes da aplicação After Application Middlewares. Haha! Agora te confundi né? É um vai-e-vem danado mesmo, mas é mais claro nos códigos que tentando explicar.


Prioridade dos Middlewares 

Mais vai-e-vem! Sim, você pode adicionar quantos middlewares quiser, seguindo a ordem que você adicionou e também pode controlar explicitamente a prioridade de seu middleware, passando um argumento(EARLY_EVENT e LATE_EVENT) adicional para os métodos de registo, fazendo que seja executado antes ou depois:
$app->before(function (Request $request) {
    // seu código
}, Application::EARLY_EVENT);

$app->before(function (Request $request) {
    // seu código
}, Application::LATE_EVENT);


O Curto-Circuito do Controlador

Isso mesmo! Dando tilt no Controller. Hehe! Se Before Middleware retornar um objeto Response, o Request dará um "curto-circuito" (os próximos middlewares não serão executados, nem o retorno de chamada rota), e o Response é passado para o After Middlewares de imediato:
$app->before(function (Request $request) {
    // redirecionar o usuário para a tela de login, 
    // se o acesso ao recurso é protegido
    if (...) {
        return new RedirectResponse('/login');
    }
});
Isto é usado para autenticação de usuários por exemplo.

Bom é mais ou menos isso. Confuso de explicar por se tratar deste Vai-e-Vem danado, mas é isso. No decorrer dos próximos artigos usaremos e será mais claro seu entendimento sobre Middleware.

Aguardo comentários.

Até a próxima pessoal! ;-)