Laravel의 미들웨어 구현 방법 살펴보기

*文
풀어 주다: 2023-03-18 22:18:01
원래의
1895명이 탐색했습니다.

Laravel의 미들웨어는 어떻게 구현되나요? 이 글은 주로 라라벨 미들웨어의 구현 원리를 소개하고, 라라벨 미들웨어의 개념, 원리, 관련 방법, 활용 기술 등을 좀 더 자세히 분석하여 도움이 필요한 친구들이 참고할 수 있습니다. 그것이 모두에게 도움이 되기를 바랍니다.

상세 내용은 다음과 같습니다.

#1 미들웨어란?

웹 애플리케이션의 경우 요청이 실제로 처리되기 전에 더 깊은 수준으로 전달되기 전에 요청에 대해 다양한 판단을 내릴 수 있습니다. 그리고 만약 if else를 이렇게 사용하게 되면, 한번 더 많은 조건을 판단해야 하게 되고, 코드 유지 관리가 더 어려워지게 되고, 시스템 간의 결합도가 높아지게 되는데, 미들웨어가 이 문제를 해결할 수 있습니다. 이러한 판단을 미들웨어로 분리하여 요청을 쉽게 필터링할 수 있습니다.

#2 Laravel의 미들웨어

Laravel에서 미들웨어의 구현은 실제로 IlluminatePipelinePipeline 클래스의 구현에 의존합니다. 먼저 미들웨어를 트리거하는 코드를 살펴보겠습니다. 매우 간단합니다. 처리 후 요청을 클로저로 전송한 다음 계속 전달하면 됩니다.

public function handle($request, Closure $next) {
  //do something for $request
  return $next($request);
}
로그인 후 복사

#3 미들웨어 내부 구현

위에서 언급한 것처럼 미들웨어는 Pipeline으로 구현되며, 해당 호출은 IlluminateRoutingRouter

return (new Pipeline($this->container))
            ->send($request)
            ->through($middleware)
            ->then(function ($request) use ($route) {
              return $this->prepareResponse(
                $request,
                $route->run($request)
              );
            });
로그인 후 복사

에서 이루어집니다. 미들웨어 실행 프로세스에서는 세 가지 메소드를 호출하는 것을 볼 수 있습니다. 이 세 가지 메소드의 코드를 살펴보겠습니다.

send 메소드

public function send($passable){
  $this->passable = $passable;
  return $this;
}
로그인 후 복사

사실 send 메소드는 미들웨어에서 파이프라인이 필요한 객체를 설정하는 역할만 합니다. 사례.

through method

public function through($pipes){
  $this->pipes = is_array($pipes) ? $pipes : func_get_args();
  return $this;
}
로그인 후 복사

through 메소드 역시 매우 간단하며, 수행해야 할 미들웨어 처리를 설정하는 것입니다.

then method

정말 이해하기 어려운게 바로 여기에 있습니다. Then 메소드 코드는 매우 간단하지만 이해하기 쉽지 않습니다.

public function then(Closure $destination){
  //then方法接受一个闭包作为参数,然后经过getInitialSlice包装,而getInitialSlice返回的其实也是一个闭包,如果还不知道什么是闭包先去看PHP文档
  $firstSlice = $this->getInitialSlice($destination);
  //反转中间件数组,主要是利用了栈的特性,用处接下来再说
  $pipes = array_reverse($this->pipes);
  //这个call_user_func先不要看,它其实就是执行了一个array_reduce返回的闭包
  return call_user_func(  
    //接下来用array_reduce来用回调函数处理数组,建议先去PHP文档读懂array_reduce的执行原理。其实arrary_reduce什么事情都没干,就是包装闭包然后移交给call_user_func来执行
    array_reduce($pipes, $this->getSlice(), $firstSlice), $this->passable
  );
}
로그인 후 복사

그럼 더 이상은 없습니다. 이렇게 하면 모든 미들웨어가 매우 우아해지지 않나요?

aray_reduce의 두 번째 매개변수에는 함수가 필요하므로 getSlice() 메서드의 소스 코드에 집중하겠습니다.

protected function getSlice(){
    return function ($stack, $pipe) {  //这里$stack
      return function ($passable) use ($stack, $pipe) {
        if ($pipe instanceof Closure) {
          return call_user_func($pipe, $passable, $stack);
        } else {
          list($name, $parameters) = $this->parsePipeString($pipe);
          return call_user_func_array([$this->container->make($name), $this->method],
          array_merge([$passable, $stack], $parameters));
        }
      };
    };
}
로그인 후 복사

클로저가 클로저를 반환하는 것을 보면 어지러움을 느낄 수도 있습니다. 단순화하기 위해 getSlice()는 함수 A를 반환하고 함수 A는 함수 B를 반환합니다. 왜 두 개의 함수를 반환합니까? 전송 프로세스 중에 객체를 전달하기 위해 $next($request) 를 사용하고 $next($request) 는 클로저가 실행된다는 것을 의미하기 때문에 이 클로저는 함수 A이고 함수 B를 반환합니다. 다음 미들웨어.

코드를 다시 단순화해 보겠습니다.

//这里的$stack其实就是闭包,第一次遍历的时候会传入$firstSlice这个闭包,以后每次都会传入下面的那个function; 而$pipe就是每一个中间件
array_reduce($pipes, function ($stack, $pipe) {  
  return function ($passable) use ($stack, $pipe) {
  };
}, $firstSlice);
로그인 후 복사

이 코드를 다시 살펴보세요.

//判断是否为闭包,这里就是判断中间件形式是不是闭包,是的话直接执行并且传入$passable[请求实例]和$stack[传递给下一个中间件的闭包],并且返回
if ($pipe instanceof Closure) {  
  return call_user_func($pipe, $passable, $stack);
//不是闭包的时候就是形如这样Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode执行
} else {  
  //解析,把名称返回,这个$parameters看了许久源码还是看不懂,应该是和参数相关,不过不影响我们的分析
  list($name, $parameters) = $this->parsePipeString($pipe); 
  //从容器中解析出中间件实例并且执行handle方法
  return call_user_func_array([$this->container->make($name), $this->method], 
  //$passable就是请求实例,而$stack就是传递的闭包
  array_merge([$passable, $stack], $parameters));  
}
로그인 후 복사

다른 그림을 살펴보세요.

반사로 인해 모든 반복은 이전 클로저와 실행해야 하는 미들웨어에서 전달됩니다. 스택의 선입후출 방식에 따라 어레이가 전송되므로 미들웨어 3이 먼저 패키징되고 미들웨어 1이 가장 바깥쪽 레이어에 배치됩니다. array_reduce는 미들웨어 코드를 실행하지 않고 미들웨어를 래핑한다는 점을 기억하세요.

이 내용을 보고 나면 array_reduce가 결국 func3을 반환하고 call_user_func(func3,$this->passable)이 실제로

return call_user_func($middleware[0]->handle, $this->passable이라는 것을 이해해야 합니다. ) , func2);

미들웨어의 핸들 코드는

public function handle($request, Closure $next) {
  return $next($request);
}
로그인 후 복사

이것은 return func2($request)와 동일하며 여기의 $request는 이전 미들웨어에서 처리됩니다. 이렇게 Zhengguo 미들웨어 프로세스는 끝났으며, 미들웨어 코드는 결국 가장 바깥쪽의 call_user_func에 의해 실행된다는 점만 기억하세요.

관련 권장사항:

Laravel Optimization Split Routing Files

Laravel은 페이지 매김 플러그인을 사용하여 사용자 정의 페이징을 구현합니다.

laravel은 APP 인터페이스(API)를 작성합니다

위 내용은 Laravel의 미들웨어 구현 방법 살펴보기의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

관련 라벨:
원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
최신 이슈
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿
회사 소개 부인 성명 Sitemap
PHP 중국어 웹사이트:공공복지 온라인 PHP 교육,PHP 학습자의 빠른 성장을 도와주세요!