2017-02-13 14 views
0

はLaravelのValidatePostSizeからハンドル()メソッドです:今

public function handle($request, Closure $next) 
{ 
    $max = $this->getPostMaxSize(); 

    if ($max > 0 && $request->server('CONTENT_LENGTH') > $max) { 
     throw new PostTooLargeException; 
    } 

    return $next($request); 
} 

、この方法は、他のミドルウェアのため$次の($リクエスト)を使用して呼ばれています。私の理解は、ハンドル()メソッドは、$ nextに翻訳されます。私はこれがどのようにボンネットの下で起こるか知りたい。

+0

コードを検索しますか? –

+0

スタック内の次のミドルウェアクロージャです。 –

+0

@ MagnusErikssonは質問の説明を見てください。私は方法で示唆しているように、その閉鎖を知っています。私が知りたいのは、handle()メソッドが$ nextを閉じるためにどのように変換されるかです。 –

答えて

2

は、単に$要求を次のコールバック$を呼び出す(ミドルウェアは「合格」することができます)アプリケーションに深く要求を渡すために。 https://laravel.com/docs/5.4/middleware#defining-middleware

Laravelが、それは、スタック内のすべての適用可能なミドルウェアを実行し、要求を処理しています。ミドルウェアは、ルート/コントローラメソッドの前および/または後に実行するように設定できます。

これを行うには、Illuminate\Pipeline\Pipelineを使用します。基本的には、array_reduceを使用してミドルウェアスタックを反復処理し、Closureを返してそのミドルウェアを実行します。この美しさは、array_reverseを使用して次のミドルウェアの実行を前のものに引き渡すことができます。


をもう少し詳しく説明するには:

Illuminate\Foundation\Http\[email protected]が呼び出されると、それはそれで次があるsendRequestThroughRouterと応答構築:

return (new Pipeline($this->app)) 
      ->send($request) 
      ->through($this->app->shouldSkipMiddleware() ? [] : $this->middleware) 
      ->then($this->dispatchToRouter()); 

PipelineIlluminate\Pipeline\Pipelineを拡張Illuminate\Routing\Pipelineです。

上記then()方法は、基本的に次のとおりです。

->then(function ($request) { 
    $this->app->instance('request', $request); 

    return $this->router->dispatch($request); 
}) 

はその後(クロージャが呼び出されていないことをこの時点で覚えている)我々は最終結果を受け入れる閉鎖とオフ始めていることを意味します。

次に、then()の方法では、前述のようにarray_reducearray_reverseセクションが発生します。ここで


(これはあなたがどのようにarray_reduce作品を知っていると仮定し)、実際にthen()方法で発生した場合の簡単な例です:

[ 
    One::class, 
    Two::class, 
    Three::class, 
]; 

function then(Closure $destination) 
{ 
    $pipeline = array_reduce(

     array_reverse($this->middlewares), 

     //Remember $nextClosure is going to be the closure returned 
     //from the previous iteration 

     function ($nextClosure, $middlewareClass) { 

      //This is the $next closure you see in your middleware 
      return function ($request) use ($nextClosure, $middlewareClass) { 

       //Resolve the middleware 
       $middleware = app($middlewareClass); 

       //Call the middleware 
       return $middleware->{$this->method}($request, $nextClosure); 
      }; 
     }, 

     //The finial closure that will be called that resolves the destination 

     function ($request) use ($destination) { 
      return $destination($request); 
     } 
    ); 

    return $pipeline($this->request); 
} 

は、我々は3つのミドルウェアを持っていると言います上記の変数$pipelineは、基本的には次のようになります。

function ($request) { 

    return app(One::class)->handle($request, function ($request) { 

     return app(Two::class)->handle($request, function ($request) { 

      return app(Three::class)->handle($request, function ($request) { 

       return $destination($request); 

      }); 
     };); 
    };); 
}; 

これが役に立ちます。

+0

もう少し詳しく教えていただけますか? Illuminate/Pipeline/Pipeline.phpですべての魔法が起こっていると思います。簡単な例が素晴らしいでしょう。 –

+0

@MayankKumarもう少し追加しました。 –

+0

パイプラインを使用せずにこれを実装したい場合、どうすればよいですか? –

1

次は、匿名関数の変数であるクロージャです。あなたのコードにはreturn $next($request);があります。 $ nextは、2番目のメソッドのパラメータに基づいてClosureです。つまり、メソッドの戻り値は、無名関数が返す値です。例えば

// this is the Closure. 
$next = function ($parameter) { 
    return $parameter . ' This message is modified by $next'; 
}; 

public function handle($message, Closure $next) 
{ 
    return $next($message); 
} 

// test the output 
$message = 'Hello World!'; 
echo handle($message, $next); // output will be 'Hello World! This message is modified by $next' 
関連する問題