이 글은 라라벨 프레임워크의 미들웨어에 대한 자세한 설명을 제공합니다. 필요한 친구들이 참고할 수 있기를 바랍니다.
laravel 미들웨어는 일부 논리 구현을 분리할 수 있어 매우 편리하며, laravel에서는
미들웨어 작성도 매우 편리합니다. 누가 그것을 사용하는지 누가 알겠습니까?
1. 데코레이터 패턴
라라벨의 미들웨어는 [데코레이터 패턴][1]이 무엇인지 살펴보겠습니다. 먼저 간단히 살펴보겠습니다. 이 패턴은 주로 문제를 해결하는 데 사용됩니다. 클래스가 동적으로 함수를 확장해야 하는 경우 상속을 사용하면 확장된 함수가 공용 함수가 됩니다. 이는 기능 재사용과 코드 분리에 도움이 되지 않습니다.
laravel에서는 이 모드를 사용하는 함수를 요청 처리 파이프라인, 즉 파이프라인이라고 합니다.
//公共接口 interface middleware { public static function handle(Closure $next); } //装饰器1 class MiddleStepOne implements middleware{ public static function handle(Closure $next) { echo "前期处理的第一步"."<br>"; $next(); echo "后期处理的第一步"."<br>"; } } //装饰器2 class MiddleStepTwo implements middleware{ public static function handle(Closure $next) { echo "前期处理的第二步"."<br>"; $next(); echo "后期处理的第二步"."<br>"; } } function goFunc() { return function ($step,$className) { return function () use ($step,$className) { return $className::handle($step); }; }; } $pip = array( MiddleStepOne::class, MiddleStepTwo::class, ); $pip = array_reverse($pip); //反转数组,以求达到要求的顺序运行 $first = function (){ echo "前期处理完毕"."<br>"; }; //实际要处理的函数 $a = array_reduce($pip,goFunc(),$first); //遍历pip数组,并将first作为第一个参数传递进去 $a(); //执行
출력:
#🎜 🎜 #이것은 데코레이터 패턴을 기반으로 한 간단한 파이프라인입니다. 그 본질은 실제로 폐쇄와 재귀를 기반으로 합니다. 이 프로그램을 분석해 보면 최종 생성된 $a 변수에 대해 실행하면 next() 함수가 있기 때문에 그 값은 대략 MiddleStepOne.handle(MiddleStepTwo.handle(first))과 같습니다. 존재하므로 이는 재귀 호출입니다. laravel의 미들웨어의 경우 구현 원리는 다음과 같습니다.
2. 라라벨의 미들웨어 및 요청 처리 파이프라인
라라벨에서는 요청을 실행하기 위한 미들웨어를 설정할 수 있습니다. 미리. 요청 입구에서 시작 public/index.php중요 코드는 다음과 같습니다. 요청을 처리하고 요청에 대한 응답을 반환합니다.
$response = $kernel->handle( $request = Illuminate\Http\Request::capture() //创建一个请求实例 );그런 다음 커널에 들어가서 IlluminateFoundationHttpKernel.php에서 특정 구현을 확인합니다.
#🎜🎜 ## 🎜🎜#
dispatchToRouter() 함수에 대해 직접 읽어보세요. 별로 많지 않습니다. 여기 말했다. 다음 단계는 흥미로운 PipeLine 클래스입니다.
<?php namespace Illuminate\Pipeline; use Closure; use RuntimeException; use Illuminate\Contracts\Container\Container; use Illuminate\Contracts\Pipeline\Pipeline as PipelineContract; class Pipeline implements PipelineContract { /** * The container implementation. * * @var \Illuminate\Contracts\Container\Container */ protected $container; /** * The object being passed through the pipeline. * * @var mixed */ protected $passable; /** * The array of class pipes. * * @var array */ protected $pipes = []; /** * The method to call on each pipe. * * @var string */ protected $method = 'handle'; /** * Create a new class instance. * * @param \Illuminate\Contracts\Container\Container|null $container * @return void */ public function __construct(Container $container = null) { $this->container = $container; } /** * Set the object being sent through the pipeline. * * @param mixed $passable * @return $this */ public function send($passable) { $this->passable = $passable; return $this; } /** * Set the array of pipes. * * @param array|mixed $pipes * @return $this */ public function through($pipes) { $this->pipes = is_array($pipes) ? $pipes : func_get_args(); return $this; } /** * Set the method to call on the pipes. * * @param string $method * @return $this */ public function via($method) { $this->method = $method; return $this; } /** * Run the pipeline with a final destination callback. * * @param \Closure $destination * @return mixed */ public function then(Closure $destination) { $pipeline = array_reduce( array_reverse($this->pipes), $this->carry(), $this->prepareDestination($destination) ); return $pipeline($this->passable); } /** * Get the final piece of the Closure onion. * * @param \Closure $destination * @return \Closure */ protected function prepareDestination(Closure $destination) { return function ($passable) use ($destination) { return $destination($passable); }; } /** * Get a Closure that represents a slice of the application onion. * * @return \Closure */ protected function carry() { return function ($stack, $pipe) { return function ($passable) use ($stack, $pipe) { if (is_callable($pipe)) { // If the pipe is an instance of a Closure, we will just call it directly but // otherwise we'll resolve the pipes out of the container and call it with // the appropriate method and arguments, returning the results back out. //如果pip也就中间件函数是一个闭包可调用函数,就直接返回这个闭包函数就行了 //这里我还没有找到对应的使用场景,后续补充 return $pipe($passable, $stack); } elseif (! is_object($pipe)) { list($name, $parameters) = $this->parsePipeString($pipe); // If the pipe is a string we will parse the string and resolve the class out // of the dependency injection container. We can then build a callable and // execute the pipe function giving in the parameters that are required. $pipe = $this->getContainer()->make($name); $parameters = array_merge([$passable, $stack], $parameters); } else { // If the pipe is already an object we'll just make a callable and pass it to // the pipe as-is. There is no need to do any extra parsing and formatting // since the object we're given was already a fully instantiated object. $parameters = [$passable, $stack]; } return method_exists($pipe, $this->method) ? $pipe->{$this->method}(...$parameters) : $pipe(...$parameters); }; }; } /** * Parse full pipe string to get name and parameters. * * @param string $pipe * @return array */ protected function parsePipeString($pipe) { list($name, $parameters) = array_pad(explode(':', $pipe, 2), 2, []); if (is_string($parameters)) { $parameters = explode(',', $parameters); } return [$name, $parameters]; } /** * Get the container instance. * * @return \Illuminate\Contracts\Container\Container * @throws \RuntimeException */ protected function getContainer() { if (! $this->container) { throw new RuntimeException('A container instance has not been passed to the Pipeline.'); } return $this->container; } }일반적으로 PipeLine 클래스의 구현은 이전에 작성한 데코레이터와 유사합니다. 문제는 protected 함수 carry() 함수 내부에서 pip가 클로저, 문자열 및 객체 처리일 때입니다.
예전에는 laravel의 미들웨어가 참 신비롭다고 생각했는데, 읽어보니 정말 그렇네요. 매우 정교하고 실제에서도 매우 유용한 모델입니다. 예를 들어, 우리가 현재 사용하고 있는 게이트웨이 프로젝트는 어떤 프레임워크도 사용하지 않기 때문에 판단 조건을 제거하고 미들웨어에 작성하여 어느 정도 모듈화된 프로그래밍을 달성합니다.
위 내용은 Laravel 프레임워크의 미들웨어에 대한 자세한 설명의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!