ホームページ  >  記事  >  バックエンド開発  >  Laravel のミドルウェアがどのように実装されているかを調べる

Laravel のミドルウェアがどのように実装されているかを調べる

*文
*文オリジナル
2018-01-02 14:05:021962ブラウズ

Laravel のミドルウェアはどのように実装されていますか?この記事では主にLaravelミドルウェアの実装原理を紹介し、Laravelミドルウェアの概念、原理、関連方法、使用スキルをより詳細に分析します。必要な友人は参考にしてください。お役に立てれば幸いです。

詳細は以下の通りです:

#1 ミドルウェアとは何ですか?

Web アプリケーションの場合、リクエストが実際に処理される前に、リクエストがより深いレベルに渡される前に、リクエストに対してさまざまな判断が行われることがあります。このように 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)
              );
            });

ミドルウェアの実行プロセスが 3 つのメソッドを呼び出していることがわかります。これら 3 つのメソッドのコードを見てみましょう:

send メソッド

public function send($passable){
  $this->passable = $passable;
  return $this;
}

実際、send メソッドはミドルウェアでパイプライン化する必要があるオブジェクトを設定するだけです。これは HTTP リクエストです。実例。

throughメソッド

public function through($pipes){
  $this->pipes = is_array($pipes) ? $pipes : func_get_args();
  return $this;
}

throughメソッドも非常に簡単で、どのミドルウェアの処理を行うかを設定するだけです。

then メソッド

ここからが本当の難しさです。then メソッドのコードは非常に単純ですが、理解するのは簡単ではありません。

rreee

これですべてのミドルウェアが渡されるのは非常にエレガントではないでしょうか。

aray_reduce の 2 番目のパラメータには関数が必要なので、getSlice() メソッドのソース コードに注目してみましょう

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
  );
}

クロージャがクロージャを返すのを見るとめまいを感じるかもしれません。単純化するために、getSlice() は関数 A を返し、関数 A は関数 B を返します。なぜ 2 つの関数を返すのでしょうか? $next($request) を使用して転送プロセス中にオブジェクトを渡します。 $next($request) は、このクロージャーが関数 A で実行され、関数 B を返すことを意味します。これは、 に渡すことができます。次のミドルウェア。

コードをもう一度単純化してみましょう:

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));
        }
      };
    };
}

このコードをもう一度見てください:

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

別の図を見てください:

すべての反復は、リフレクションにより、前のクロージャと実行する必要があるミドルウェアに渡されます。配列はスタックの先入れ後出し機能に基づいて転送されるため、ミドルウェア 3 が最初にパッケージ化され、ミドルウェア 1 が最外層になります。 array_reduce はミドルウェア コードを実行するのではなく、ミドルウェアをラップすることに注意してください。

これを見れば理解できるはずですが、array_reduce は最終的に func3 を返し、その後 call_user_func(func3,$this->passable) が実際には

return call_user_func($middleware[0]->handle, $this->passable) になります。 ) , func2);

ミドルウェアのハンドル コードは次のとおりです:

//判断是否为闭包,这里就是判断中间件形式是不是闭包,是的话直接执行并且传入$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));  
}

これは return func2($request) と同等であり、ここでの $request は前のミドルウェアによって処理されます。これで Zhengguo ミドルウェアのプロセスは終了しましたが、理解するのが少し混乱するでしょう。最後に、最も外側の call_user_func がミドルウェア コードを実行することを覚えておいてください。

LaravelはPaginationプラグインを使用してカスタムページングを実装します

laravelはAPPインターフェース(API)を書き込みます

以上がLaravel のミドルウェアがどのように実装されているかを調べるの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。