2017-02-13 2 views
0

ist hier ein Handgriff() -Methode von ValidatePostSize des Laravel:

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

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

    return $next($request); 
} 

Nun, diese Methode $ next ($ request) für eine andere Middleware aufgerufen wird. Was mein Verständnis ist, dass handle() Methode zu $ nächste übersetzt werden. Ich möchte wissen, wie das unter der Haube passiert.

+0

den Code nachschlagen? –

+0

Es ist der nächste Middleware-Abschluss im Stapel. –

+0

@MagnusEriksson schauen Sie sich die Beschreibung der Frage. Ich kenne seine Schließung, wie es in der Methode angedeutet hat. Ich möchte wissen, wie die Methode handle() in closure $ next übersetzt wird. –

Antwort

2

Um die Anforderung tiefer in die Anwendung übergeben (so dass die Middleware "pass"), einfach die $ nächste Rückruf rufen mit dem $ Anfrage. https://laravel.com/docs/5.4/middleware#defining-middleware

Wenn Laravel eine Anforderung ist der Umgang mit ihm läuft die ganze anwendbar Middleware im Stapel. Middleware kann so eingestellt werden, dass sie vor und/oder nach der Route/Controller-Methode ausgeführt wird.

Um dies zu tun, verwendet Laravel Illuminate\Pipeline\Pipeline. Im Wesentlichen verwendet es array_reduce, um über den Middleware-Stapel zu iterieren, der dann einen Closure zurückgibt, um diese Middleware auszuführen. Das Schöne daran ist die Verwendung von array_reverse, wodurch die nächste Middleware-Ausführung an die vorherige weitergegeben werden kann.


Um etwas mehr zu erarbeiten:

Wenn die Illuminate\Foundation\Http\[email protected] es die Antwort baut mit sendRequestThroughRouter genannt wird, die in ihm ist folgendes:

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

Pipeline ist Illuminate\Routing\Pipeline die Illuminate\Pipeline\Pipeline erstreckt .

Die then() oben beschriebene Methode ist im Wesentlichen:

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

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

Dann bedeutet, dass wir mit einem Verschluss Anfahren sind, dass die Endergebnisse akzeptiert (an dieser Stelle daran erinnern, dass Schließung wird nicht genannt wurde).

Dann, in der then() Methode, die array_reduce und array_reverse Abschnitt wie oben erwähnt passiert.


Hier ist ein vereinfachtes Beispiel, wenn tatsächlich geschieht in der then() Methode (dies voraus, dass Sie wissen, wie array_reduce Werke):

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

sagen wir 3 Middle haben:

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

Die obige $pipeline Variable wäre grundsätzlich:

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

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

Hoffe, das hilft!

+0

Könnten Sie bitte etwas mehr ausarbeiten? Ich denke, die ganze Magie passiert in Illuminate/Pipeline/Pipeline.php. Ein einfaches Beispiel wird großartig sein. –

+0

@MayankKumar Ich habe ein bisschen mehr hinzugefügt. –

+0

Wenn ich das ohne Pipeline implementieren möchte, wie soll ich angehen? –

1

Weiter ist eine Schließung, eine Variable der anonymen Funktion. In Ihrem Code haben Sie return $next($request);. $ next ist eine Closure, basierend auf Ihrem zweiten Methodenparameter. Das bedeutet, dass der Rückgabewert Ihrer Methode von der anonymen Funktion zurückgegeben wird.

Zum Beispiel:

// 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' 
Verwandte Themen