Heim  >  Artikel  >  PHP-Framework  >  Detaillierte Erläuterung der Middleware im Laravel-Framework

Detaillierte Erläuterung der Middleware im Laravel-Framework

不言
不言nach vorne
2018-10-15 14:43:103168Durchsuche

Dieser Artikel bietet Ihnen eine detaillierte Erklärung der Middleware des Laravel-Frameworks. Ich hoffe, dass er für Freunde in Not hilfreich ist.

Laravel-Middleware ist eine sehr praktische Sache, die etwas Logik entkoppeln kann, und in Laravel ist das Schreiben von
Middleware auch sehr praktisch. Wer weiß, wer es nutzt.

1. Dekorationsmodus

Die Middleware in Laravel verwendet den Dekorationsmodus [1], lassen Sie uns zuerst etwas darüber erfahren Sprechen Sie hier darüber. Dieses Modell wird hauptsächlich zur Lösung des Problems verwendet. Wenn eine Klasse Funktionen dynamisch erweitern muss, wird die Unterklasse durch die Verwendung erweitert, und die erweiterte Funktion ist für die Wiederverwendung von Funktionen nicht förderlich und Code-Entkopplung.

In Laravel wird die Funktion, die dieses Muster verwendet, als Anforderungsverarbeitungspipeline bezeichnet, also Pipeline

//公共接口
interface middleware {
        public static function handle(Closure $next);
    }
//装饰器1
class MiddleStepOne implements middleware{
        public static function handle(Closure $next) {
            echo "前期处理的第一步"."<br>";
            $next();
            echo "后期处理的第一步"."<br>";
        }
    }
//装饰器2
class MiddleStepTwo implements middleware{
    public static function handle(Closure $next) {
        echo "前期处理的第二步"."<br>";
        $next();
        echo "后期处理的第二步"."<br>";
    }
}

function goFunc() {
    return function ($step,$className) {
      return function () use ($step,$className) {
          return $className::handle($step);
      };
    };
}

$pip = array(
    MiddleStepOne::class,
    MiddleStepTwo::class,
);
$pip = array_reverse($pip);  //反转数组,以求达到要求的顺序运行
$first = function (){
    echo "前期处理完毕"."<br>";
};  //实际要处理的函数
$a = array_reduce($pip,goFunc(),$first); //遍历pip数组,并将first作为第一个参数传递进去
$a(); //执行

Ausgabe:

Detaillierte Erläuterung der Middleware im Laravel-Framework

Dies ist eine einfache Pipeline, die auf dem Decorator-Muster basiert. Sein Wesen basiert tatsächlich auf Schließung und Rekursion.

Bei der Analyse dieses Programms ist der Wert für die schließlich generierte $a-Variable ungefähr wie MiddleStepOne.handle(MiddleStepTwo.handle(first)), da es eine next( im Handle)-Funktion gibt , es handelt sich also um einen rekursiven Aufruf. Für die Middleware von Laravel ist das Implementierungsprinzip dasselbe.

2. Middleware und Anforderungsverarbeitungspipeline in Laravel

In Laravel können wir vor der Anforderungsausführung eine Vorverarbeitung durchführen, indem wir Middleware festlegen.

Beginnen Sie mit dem Anforderungseingang public/index.php

Detaillierte Erläuterung der Middleware im Laravel-Framework

Das Wichtige ist dieser Code: Das heißt, Verarbeitung der Anfrage, Rückgabe der Antwort auf die Anfrage

$response = $kernel->handle(
$request = Illuminate\Http\Request::capture() //创建一个请求实例
);

Dann betreten wir den Kernel, um seine spezifische Implementierung in IlluminateFoundationHttpKernel.php zu sehen

Detaillierte Erläuterung der Middleware im Laravel-Framework

Detaillierte Erläuterung der Middleware im Laravel-Framework
Bitte lesen Sie selbst über die Funktion „dispatchToRouter()“, daher werde ich hier nicht auf Details eingehen.

Der nächste Schritt ist die aufregende PipeLine-Klasse

<?php namespace Illuminate\Pipeline;

use Closure;
use RuntimeException;
use Illuminate\Contracts\Container\Container;
use Illuminate\Contracts\Pipeline\Pipeline as PipelineContract;

class Pipeline implements PipelineContract
{
    /**
     * The container implementation.
     *
     * @var \Illuminate\Contracts\Container\Container
     */
    protected $container;

    /**
     * The object being passed through the pipeline.
     *
     * @var mixed
     */
    protected $passable;

    /**
     * The array of class pipes.
     *
     * @var array
     */
    protected $pipes = [];

    /**
     * The method to call on each pipe.
     *
     * @var string
     */
    protected $method = &#39;handle&#39;;

    /**
     * Create a new class instance.
     *
     * @param  \Illuminate\Contracts\Container\Container|null  $container
     * @return void
     */
    public function __construct(Container $container = null)
    {
        $this->container = $container;
    }

    /**
     * Set the object being sent through the pipeline.
     *
     * @param  mixed  $passable
     * @return $this
     */
    public function send($passable)
    {
        $this->passable = $passable;

        return $this;
    }

    /**
     * Set the array of pipes.
     *
     * @param  array|mixed  $pipes
     * @return $this
     */
    public function through($pipes)
    {
        $this->pipes = is_array($pipes) ? $pipes : func_get_args();

        return $this;
    }

    /**
     * Set the method to call on the pipes.
     *
     * @param  string  $method
     * @return $this
     */
    public function via($method)
    {
        $this->method = $method;

        return $this;
    }

    /**
     * Run the pipeline with a final destination callback.
     *
     * @param  \Closure  $destination
     * @return mixed
     */
    public function then(Closure $destination)
    {
        $pipeline = array_reduce(
            array_reverse($this->pipes), $this->carry(), $this->prepareDestination($destination)
        );

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

    /**
     * Get the final piece of the Closure onion.
     *
     * @param  \Closure  $destination
     * @return \Closure
     */
    protected function prepareDestination(Closure $destination)
    {
        return function ($passable) use ($destination) {
            return $destination($passable);
        };
    }

    /**
     * Get a Closure that represents a slice of the application onion.
     *
     * @return \Closure
     */
    protected function carry()
    {
        return function ($stack, $pipe) {
            return function ($passable) use ($stack, $pipe) {
                if (is_callable($pipe)) {
                    // If the pipe is an instance of a Closure, we will just call it directly but
                    // otherwise we'll resolve the pipes out of the container and call it with
                    // the appropriate method and arguments, returning the results back out.
                    //如果pip也就中间件函数是一个闭包可调用函数,就直接返回这个闭包函数就行了
                    //这里我还没有找到对应的使用场景,后续补充
                    return $pipe($passable, $stack);
                } elseif (! is_object($pipe)) {
                    list($name, $parameters) = $this->parsePipeString($pipe);

                    // If the pipe is a string we will parse the string and resolve the class out
                    // of the dependency injection container. We can then build a callable and
                    // execute the pipe function giving in the parameters that are required.
                    $pipe = $this->getContainer()->make($name);

                    $parameters = array_merge([$passable, $stack], $parameters);
                } else {
                    // If the pipe is already an object we'll just make a callable and pass it to
                    // the pipe as-is. There is no need to do any extra parsing and formatting
                    // since the object we're given was already a fully instantiated object.
                    $parameters = [$passable, $stack];
                }

                return method_exists($pipe, $this->method)
                                ? $pipe->{$this->method}(...$parameters)
                                : $pipe(...$parameters);
            };
        };
    }

    /**
     * Parse full pipe string to get name and parameters.
     *
     * @param  string $pipe
     * @return array
     */
    protected function parsePipeString($pipe)
    {
        list($name, $parameters) = array_pad(explode(':', $pipe, 2), 2, []);

        if (is_string($parameters)) {
            $parameters = explode(',', $parameters);
        }

        return [$name, $parameters];
    }

    /**
     * Get the container instance.
     *
     * @return \Illuminate\Contracts\Container\Container
     * @throws \RuntimeException
     */
    protected function getContainer()
    {
        if (! $this->container) {
            throw new RuntimeException('A container instance has not been passed to the Pipeline.');
        }

        return $this->container;
    }
}

Im Allgemeinen ähnelt die Implementierung der PipeLine-Klasse dem Dekorator, den ich zuvor geschrieben habe 🎜>Geschützte Funktion Innerhalb der Funktion „carry()“ ist die Verarbeitung von pip ein Abschluss, eine Zeichenfolge und ein Objekt.


Früher dachte ich, dass die Middleware von Laravel eine sehr mysteriöse Sache ist, aber nachdem ich sie gelesen hatte, wurde mir klar, dass sie einfach so ist. Dieses Modell ist auch für die tatsächliche Entwicklung sehr hilfreich Beispielsweise verwenden wir derzeit ein Gateway-Projekt. Da kein Framework verwendet wurde, wurden die Beurteilungsbedingungen entfernt und in Middleware geschrieben, wodurch ein gewisser Grad an modularer Programmierung erreicht wurde.

Das obige ist der detaillierte Inhalt vonDetaillierte Erläuterung der Middleware im Laravel-Framework. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:segmentfault.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen