2017-02-13 9 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); 
} 

Теперь этот метод вызывается с помощью следующего ($ запроса) $ для другого Middleware. Насколько я понимаю, handle() метод перевести на $ next. Я хочу знать, как это происходит под капотом.

+0

посмотреть код? –

+0

Это следующее промежуточное закрытие в стеке. –

+0

@MagnusEriksson посмотрите описание вопроса. Я знаю его закрытие, поскольку он намекнул в методе. Я хочу знать, как метод handle() переводится в закрытие $ next. –

ответ

2

Чтобы передать запрос глубже в приложение (это позволяет промежуточного слоя на «проход»), просто вызовите $ следующий обратный вызов с запросом $. https://laravel.com/docs/5.4/middleware#defining-middleware

Когда Laravel обрабатывает запрос, который она запускает все применимое промежуточное программное обеспечение в стеке. Средство промежуточного уровня можно настроить для запуска до и/или после метода маршрута/контроллера.

Для этого 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()); 

Pipeline является Illuminate\Routing\Pipeline, который проходит Illuminate\Pipeline\Pipeline ,

then() выше метод является по существу:

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

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

Тогда означает, что мы трогание с крышкой, которая принимает конечные результаты (помните, в этой точке, что закрытие не было названо).

Тогда, в методе then(), array_reduce и array_reverse раздел как упомянуто выше происходит.


Вот упрощенный пример, когда на самом деле происходит в методе then() (это предполагает, что вы знаете, как array_reduce работы):

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 промежуточное программное:

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

Переменная выше $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

Next - Закрытие, переменная анонимной функции. В вашем коде у вас есть return $next($request);. $ next - это закрытие, основанное на вашем втором параметре метода. Это означает, что возвращаемое значение вашего метода - это то, что возвращает анонимная функция.

Например:

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