O Laravel é um sistema verdadeiramente grande e complexo que tenta resolver a maioria das tarefas diárias de um desenvolvedor web da maneira mais elegante e coletar o maior número possível de ferramentas e, o mais importante, com o máximo de interface humana possível.
E hoje vamos nos concentrar em uma dessas ferramentas, ou melhor, no seu uso e implementação pelo programador. A falta de documentação completa, bem como a falta de artigos em russo e um número muito pequeno de artigos estrangeiros, levaram-me a decidir revelar um certo véu de sigilo sobre esse recurso interessante da estrutura e escolher esse tópico como meu primeiro artigo sobre Habré.
Middleware
Este artigo pressupõe que o leitor já esteja familiarizado com o uso básico dessa funcionalidade da estrutura, portanto, não vou me deter neste ponto por muito tempo.
Pronto para uso, o Laravel nos fornece uma funcionalidade bastante poderosa para filtrar solicitações HTTP recebidas em nosso aplicativo. Estamos falando do
Middleware amado (ou não) de todos - o desenvolvedor encontra essas classes rapidamente no caminho para dominar o Laravel, enquanto lê a seção "Noções básicas" da documentação oficial, e isso não é surpreendente - o Middleware é um dos principais e mais importantes tijolos com base nos quais todo o sistema é construído.
Exemplos de casos de usuário padrão desse componente no Laravel são:
EncryptCookies / RedirectIfAuthenticated / VerifyCsrfToken e, como exemplo de uma implementação personalizada, você pode citar a localização de aplicativos de middleware (definindo a localização necessária com base em determinados dados da solicitação) antes de transferir a solicitação ainda mais.
Mais fundo no abismo
Desista da esperança de que todos venham aqui
Bem, agora que os principais pontos terminaram - podemos mergulhar em um lugar terrível para muitos - em alfa e ômega, o começo e o fim - nas
fontes do
Laravel . Aqueles que tentaram fechar o artigo imediatamente - não se apresse. De fato, no código-fonte dessa estrutura, quase não há nada realmente complicado do lado conceitual - os criadores estão claramente tentando não apenas criar uma interface clara e conveniente para trabalhar com sua ideia, mas também estão tentando fazer o mesmo diretamente no nível do código-fonte, o que não pode para não agradar.
Tentarei explicar o conceito de como o
Middleware e o
Pipeline funcionam no nível do código e da lógica o mais simples e acessível possível, e tentarei não entrar nisso - onde isso não é necessário na estrutura do artigo. Portanto, se há pessoas nos comentários que conhecem todas as linhas de origem de cor, peço que se abstenha de criticar minha narração superficial. Mas quaisquer recomendações e correções de imprecisões são bem-vindas.
Middleware - através das barricadas
Acredito que aprender qualquer coisa é sempre mais fácil quando bons exemplos são fornecidos. Portanto, convido você e eu a estudar esta besta misteriosa sob o nome
Pipeline . Se esses homens valentes realmente existirem, antes de continuar lendo, precisaremos instalar uma versão vazia do projeto Laravel 5.7 - a versão deve-se apenas ao fato de ser a última no momento da escrita, todas as opções acima devem ser idênticas pelo menos à versão 5.4. Quem quer apenas conhecer a essência e as conclusões do artigo pode pular esta parte com segurança.
O que poderia ser melhor do que estudar o comportamento de um componente, exceto estudar o comportamento já incorporado no sistema? Talvez algo possa, mas faremos sem complicações desnecessárias e iniciaremos nossa análise com o Middleware padrão - ou seja, com o mais simples e mais compreensível de toda a turma -
RedirectIfAuthenticated :
RedirectIfAuthenticated.phpclass RedirectIfAuthenticated { public function handle($request, Closure $next, $guard = null) { if (Auth::guard($guard)->check()) { return redirect('/'); } return $next($request); } }
Em qualquer classe clássica de middleware, existe um método principal que deve processar diretamente a solicitação e passar o processamento para o próximo da cadeia - no nosso caso, esse é o método
handle . Nesta classe em particular, o processamento da solicitação é bastante simples - "se o usuário estiver autorizado, redirecione-o para a página principal e, assim, encerre a cadeia".
Se observarmos o registro deste Middleware em
app / Http / Kernel.php , veremos que ele está registrado no 'route middleware'. Para descobrirmos como o sistema funciona com esse middleware, vamos para a classe da qual nosso
aplicativo / Http / Kernel herda - e herda da classe
Illuminate \ Foundation \ Http \ Kernel . Nesta fase, abriremos diretamente os portões para o
inferno, o código fonte de nossa estrutura, ou melhor, para a parte mais importante e principal dela - para o núcleo do trabalho com HTTP. A propósito, quem se importa - o Laravel é baseado em muitos componentes do
Symfony , especificamente nesta parte - no
HttpFoundation e no
HttpKernel .
A definição e implementação do nosso middleware no construtor do kernel é a seguinte:
Illuminate \ Foundation \ Http \ Kernel (aplicativo $ app, roteador $ roteador) public function __construct(Application $app, Router $router) { $this->app = $app; $this->router = $router; $router->middlewarePriority = $this->middlewarePriority; foreach ($this->middlewareGroups as $key => $middleware) { $router->middlewareGroup($key, $middleware); } foreach ($this->routeMiddleware as $key => $middleware) { $router->aliasMiddleware($key, $middleware); } }
O código é bastante simples e direto - para cada middleware na matriz, o registramos com um alias / index em nosso roteador. Os métodos aliasMiddleware e middlewareGroups da nossa classe Route estão apenas adicionando middleware a uma das matrizes do objeto roteador. Mas isso não está incluído no contexto do artigo, então pularemos este momento e seguiremos em frente.
O que realmente interessa é o método
sendRequestThroughRoute , que literalmente traduz como
enviar uma solicitação por meio da rota :
Illuminate \ Foundation \ Http \ Kernel :: sendRequestThroughRouter ($ request) protected function sendRequestThroughRouter($request) {
Como parâmetro, este método recebe uma solicitação. Neste ponto, devemos examinar novamente nosso código
RedirectIfAuthenticated . Também recebemos uma solicitação no método
handle do nosso middleware; precisaremos dessa nota um pouco mais tarde.
O código acima possui uma interface muito clara e legível -
"Pipeline", que envia uma solicitação através de cada um dos middlewares registrados e depois a "transfere" para o roteador . Charmoso e maravilhoso. Penso que, nesta fase, não tentaremos decompor mais esta seção do código, apenas descreverei brevemente o papel desta seção em todo o sistema:
Antes de uma solicitação entrar no seu controlador, muitas ações passam, desde a simples análise do próprio URL até a inicialização da classe
Request . O middleware também está envolvido nessa
cadeia de ação. As próprias classes de middleware implementam o (quase) padrão de design da
Cadeia de Responsabilidade ,
ou Cadeia de Responsabilidade , de modo que cada classe específica de midleware é apenas um elo na cadeia.
Acima, não acabamos de retornar à nossa classe
RedirectIfAuthenticated originalmente considerada. A solicitação está "circulando" ao longo da cadeia, incluindo a que passa por tudo o necessário para a rota do middleware. Esse momento nos ajudará a trabalhar com nossos próprios elos em nossa própria cadeia, mais sobre isso mais tarde.
Gasoduto - Esgoto de nossa aplicação
Um exemplo da implementação do
Pipeline que vimos acima. Mas o objetivo do artigo não era apenas explicar a operação desse componente no nível de integração com o Laravel, mas também explicar o princípio básico de trabalhar com essa classe em nosso próprio código.
A própria classe pode ser encontrada por sua definição completa com espaço para nome:
Iluminar \ Pipeline \ Pipeline
Pode haver muitas aplicações para esse componente, dependendo da tarefa específica que você precisa resolver, mas uma das motivações mais óbvias é o requisito de criar sua própria cadeia de manipuladores de solicitações, o que não interfere nos processos de todo o sistema e é determinado exclusivamente no nível da lógica de negócios. Além disso, a interface da classe possui um nível suficiente de abstração e funcionalidade suficiente para implementar diferentes tipos de filas.
Exemplo de implementação no Laravel
Implementamos a cadeia de consulta mais simples e remota da realidade. Usaremos a string "HELLO WORLD" como dados e, com a ajuda de dois manipuladores, formaremos a string "Hello User". O código é intencionalmente simplificado.
Antes da implementação imediata de nosso próprio "Pipe", precisamos identificar os elementos desse pipe. Os elementos são escritos por analogia com o middleware:
Definindo manipuladoresStrToLowerAction.php:
use Closure; class StrToLowerAction { public function handle(string $content, Closure $next) { $content = strtolower($content); return $next($content); } }
SetUserAction.php:
use Closure; class SetUserAction { public function handle(string $content, Closure $next) { $content = ucwords(str_replace('world', 'user', $content)); return $next($content); } }
Em seguida, criamos um "pipeline", determinamos que tipo de dados queremos enviar sobre ele, determinamos através de qual coleção de processadores queremos enviar esses dados e também definimos um retorno de chamada, que recebe como argumento que nossos dados passaram por toda a cadeia. Caso os dados em toda a cadeia permaneçam inalterados, a parte com retorno de chamada pode ser omitida:
$pipes = [ StrToLowerAction::class, SetUserNameAction::class ]; $data = 'Hello world'; $finalData = app(Pipeline::class) ->send($data)
Além disso, se você deseja ou precisa definir seu próprio método em manipuladores, a interface Pipeline fornece um método
via ('method_name') especial , então o processamento em cadeia pode ser escrito desta maneira:
$finalData = app(Pipeline::class) ->send($data) ->through($pipes) ->via('handle')
Diretamente, os dados que passamos pelos processadores podem ser absolutamente qualquer coisa, bem como a interação com eles. Digitar dicas e definir o tipo do objeto retornado na cadeia ajudará a evitar erros de integridade dos dados.
Conclusão
O Laravel fornece um grande número de classes integradas, e a flexibilidade de muitas delas nos permite desenvolver algo complexo com simplicidade suficiente. Este artigo examinou a possibilidade de criar filas simples para solicitações com base na classe Pipeline incorporada ao Laravel. As implementações dessa classe no código final podem ser completamente diferentes, e a flexibilidade dessa ferramenta permite que você se livre de muitas ações desnecessárias ao criar determinados algoritmos.
Como usar especificamente esse recurso da estrutura depende das tarefas atribuídas a você.