Laravel middleware code presentation

protected function sendRequestThroughRouter($request)
{
    # $this->app->instance('request', $request);

    # Facade::clearResolvedInstance('request');

    # $this->bootstrap();

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

new \Illuminate\Routing\Pipeline($this->app):
public function __construct(Container $container = null)
{
    $this->container = $container;
}
public function send($passable)
{
    $this->passable = $passable;

    return $this;
}
public function through($pipes)
{
    # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
    # $this->middleware = [ #
    # \Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::class, #
    # \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class, #
    # \App\Http\Middleware\TrimStrings::class, #
    # \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class, #
    #]; #
    # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
    $this->pipes = is_array($pipes)?$pipes : func_get_args();

    return $this;
}
// The nature of middleware
public function then(Closure $destination)
{
    $pipeline = array_reduce(
        array_reverse($this->pipes), $this->carry(), $this->prepareDestination($destination));// Return an anonymous function that takes one argument
    return $pipeline($this->passable);
}
// Note that this is the parent of a subclass called carry. The difference is that the subclass adds exception handling
protected function carry()
{
    // Take the anonymous function $stack and $PIPE arguments, return the anonymous function, and pass it in as the first iteration of the $stack argument.
    return function ($stack.$pipe) {
        return function ($passable) use ($stack.$pipe) {
            if ($pipe instanceof Closure) {
                return $pipe($passable.$stack);
            } elseif (! is_object($pipe)) {
                list($name.$parameters) = $this->parsePipeString($pipe);

                $pipe = $this->getContainer()->make($name);

                $parameters = array_merge([$passable.$stack].$parameters);
            } else {
                $parameters = [$passable.$stack];
            }
            The middleware provides a convenient mechanism to filter HTTP requests coming into the application
            $this->method = 'handle'; $this->method = 'handle
            return $pipe- > {$this->method}(...$parameters);
        };
    };
}
protected function parsePipeString($pipe)
{
    / / pipe without parameters (class) or pipe with parameters (parameter to split) (class: param1, param2, param3...).
    list($name.$parameters) = array_pad(explode(':'.$pipe.2), 2[]);if (is_string($parameters)) {
        $parameters = explode(', '.$parameters);
    }
    // $parameters for [] array or [param1,param2,param3...]
    return [$name.$parameters];
}
protected function prepareDestination(Closure $destination)
{
    return function ($passable) use ($destination) {
        return $destination($passable);
    };
Copy the code

precondition

Array_reduce takes three arguments. The first argument takes an array, the second argument is the function name (which can also be an anonymous function, with two arguments representing result and result and result and item), and the third argument (optional), which is treated as if it were the first value in the array. Or as the final return value if the array is empty. Anonymous functions, also called closures, allow the temporary creation of unnamed functions. These are implemented using closures. 3. When a Closure function is assigned, PHP automatically converts the expression into a built-in Closure class object that performs the assignment. 4. When the Closure function uses external data, it generates an array of static properties in the Closure object. 5. When a Closure function uses parameters, it generates an array of parameter properties in the Closure object.

public function then(Closure $destination)
    {
        $pipeline = array_reduce(
            array_reverse($this->pipes), $this->carry(), $this->prepareDestination($destination));return $pipeline($this->passable);
    }
Copy the code

The process for generating the final anonymous function:

Array_reduce returns the following simplified anonymous function when executed for the first time, and will continue to iterate as the first argument:object(Closure)#id (1) {
          ["static"] = >array(2) {["stack"] = >object(Closure)#1 (0) { // $this->prepareDestination($destination)
            }
            ["pipe"] = >string(15) "Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull"}} The second time:object(Closure)#id (1) {
          ["static"] = >array(2) {["stack"] = >object(Closure)#id (1) {
              ["static"] = >array(2) {["stack"] = >object(Closure)#1 (0) { // $this->prepareDestination($destination)
                }
                ["pipe"] = >string(15) "Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull"}} ["pipe"] = >string(15) "App\Http\Middleware\TrimStrings"}} Third time:object(Closure)#id (1) {
          ["static"] = >array(2) {["stack"] = >object(Closure)#id (1) {
              ["static"] = >array(2) {["stack"] = >object(Closure)#id (1) {
                  ["static"] = >array(2) {["stack"] = >object(Closure)#1 (0) { // $this->prepareDestination($destination)
                    }
                    ["pipe"] = >string(15) "Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull"}} ["pipe"] = >string(15) "App\Http\Middleware\TrimStrings"}} ["pipe"] = >string(15) "Illuminate\Foundation\Http\Middleware\ValidatePostSize"}}Copy the code

And so on, you end up with an anonymous function that takes one argument and uses the above recursive pipe and PIPE and pipe and stack internally.

function ($passable) {
        if ($pipe instanceof Closure) {
            return $pipe($passable.$stack);
        } elseif (! is_object($pipe)) {
            list($name.$parameters) = $this->parsePipeString($pipe);

            $pipe = $this->getContainer()->make($name); // Instantiate middleware

            $parameters = array_merge([$passable.$stack].$parameters);
        } else {
            $parameters = [$passable.$stack];
        }
        return $pipe- > {$this->method}(...$parameters);  // Syntax sugar pattern, because the Middleware parameter is optional
    };
Copy the code

Array_reverse (array_reverse, array_reverse, array_reverse, array_reverse, array_reverse, array_reverse) If it is a string, it is parsed into the corresponding classes and parameters, the make class, and then an array of parameters. Pipe is called directly if it is an anonymous function. If it is a string, it is parsed into the corresponding classes and parameters, the make class, and then an array of parameters. Pipe is called directly if it is an anonymous function. If it is a string, it is parsed into the corresponding classes and parameters, the make class, and then an array of parameters. Finally call pipe-> Handle)

The outermost layer ($pipe= Illuminate, Foundation, Http, Middleware \ CheckForMaintenanceMode) : (new \Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode)->handle($passable.$stack) is called after the preceding operation$stack($passable), proceed to the next layer, the next layer ($pipe=Illuminate\Foundation\Http\Middleware\ValidatePostSize):
    (new \Illuminate\Foundation\Http\Middleware\ValidatePostSize)->handle($passable.$stack) is called after the preceding operation$stack($passable), continue to the next layer and so on, when the pre-tasks of each layer of middleware are all completed, that is, recursive execution to the innermost layer (routing distribution, parsing requests, return response), and then go back from the innermost layer to perform the post-tasks of each layer of middleware. At this point, the response for this request is returned.Copy the code

The innermost layer (i.e. route distribution, request parsing, return response) operation code display, subsequent analysis: that is to execute destination(destination(destination(passable) anonymous function, located in the following method.

protected function prepareDestination(Closure $destination)
    {
        return function ($passable) use ($destination) {
            return $destination($passable);
        };
    }
    $destination:
    protected function dispatchToRouter()
    {
        return function ($request) {
            $this->app->instance('request'.$request);

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

Note: all post-operations are executed to the innermost layer, and will be executed layer by layer when recursing back.

The above content hopes to help you, more PHP factory PDF, PHP advanced architecture video materials, PHP wonderful good article can be searched on wechat: PHP open source community

2021 Jinsanyin four big factory interview real questions collection, must see!

Four years of PHP technical articles collation collection – PHP framework

A collection of four years’ worth of PHP technical articles – Microservices Architecture

Distributed Architecture is a four-year collection of PHP technical articles

Four years of PHP technical essays – High Concurrency scenarios

Four years of elite PHP technical article collation collection – database