Heim > PHP-Framework > Denken Sie an PHP > ThinkPHP6 lädt Middleware und analysiert mehrere Anwendungen

ThinkPHP6 lädt Middleware und analysiert mehrere Anwendungen

藏色散人
Freigeben: 2021-07-13 13:52:42
nach vorne
3520 Leute haben es durchsucht

1. Loading Middleware

Ein Artikel, den ich zuvor geschrieben habeanalysierte die Initialisierung der Anwendung, die in der run()-Methode der Http-Klassenerweiterung aufgerufen wird Analyse von $this->initialize(), der ersten Codezeile in der runWithRequest()-Methode. Schauen wir uns noch einmal die ersten paar Zeilen der runWithRequest()-Methode an:

protected function runWithRequest(Request $request)
{
    $this->initialize();

    // 加载全局中间件
    $this->loadMiddleware();
    .
    .
    .
Nach dem Login kopieren
Nachdem die Anwendung initialisiert wurde, besteht der nächste Schritt darin, die Middleware zu verarbeiten.

Initialisierung der Middleware-Klasse

loadMiddleware-Methode:

protected function loadMiddleware(): void
{
    if (is_file($this->app->getBasePath() . 'middleware.php')) {
        $this->app->middleware->import(include $this->app->getBasePath() . 'middleware.php');
    }
}
Nach dem Login kopieren
ist immer noch eine gängige Routine. Verwenden Sie $this->app->middleware, um Middleware zu instanziieren und ihre Instanz abzurufen.

Middleware importieren

Nachdem das Programm die Instanz der Middleware-Klasse über $this->app->middleware abgerufen hat, ruft es die Importmethode auf und übergibt die aus der Datei „middleware.php“ gelesene Datei im „ app“-Verzeichnis. Daten. Der ursprüngliche Inhalt der Datei lautet wie folgt (alle Kommentare wurden ursprünglich auskommentiert):

return [
    // 全局请求缓存
    // \think\middleware\CheckRequestCache::class,
    // 多语言加载
     \think\middleware\LoadLangPack::class,
    // Session初始化
    // \think\middleware\SessionInit::class,
    // 页面Trace调试
     \think\middleware\TraceDebug::class,
];
Nach dem Login kopieren
Um zu untersuchen, wie die Middleware geladen wird, entfernen Sie zunächst zwei Kommentare, dh fügen Sie zwei Middleware hinzu. Schauen Sie sich als nächstes die Importmethode an:

public function import(array $middlewares = [], string $type = 'global'): void
{
    foreach ($middlewares as $middleware) {
        $this->add($middleware, $type);
    }
}
Nach dem Login kopieren
Diese Methode übergibt ein Array von Middleware und einen Middleware-Typ. Der Standardwert ist global. Der Schlüssel ist die darin enthaltene Add-Methode. Springen Sie zur Add-Methode:

public function add($middleware, string $type = 'route'): void
{
    if (is_null($middleware)) {
        return;
    }

    $middleware = $this->buildMiddleware($middleware, $type);

    if ($middleware) {
        $this->queue[$type][] = $middleware;
        // 去除重复
        $this->queue[$type]   = array_unique($this->queue[$type], SORT_REGULAR);
    }
}
Nach dem Login kopieren
Tatsächlich ist die eigentliche Arbeit die buildMiddleware-Methode. Gehen Sie direkt zu:

protected function buildMiddleware($middleware, string $type): array
{
    // 是否是数组
    if (is_array($middleware)) {
        // 列出中间件及其参数
        // 这里说明我们可以给中间件传入参数,且形式为 [中间件, 参数]
        list($middleware, $param) = $middleware;
    }
    // 是否是一个闭包
    // 说明中间件可以是一个闭包
    if ($middleware instanceof \Closure) {
        //返回闭包和参数
        return [$middleware, $param ?? null];
    }
    // 排除了上面几种类型,且不是字符串,抛出错误
    if (!is_string($middleware)) {
        throw new InvalidArgumentException('The middleware is invalid');
    }

    //中间件别名检查
     $alias = $this->app->config->get('middleware.alias', []);

     if (isset($alias[$middleware])) {
        $middleware = $alias[$middleware];
    }

    //如果中间件有包含中间件(说明中间件可以嵌套)
    //再走一遍「import」递归解析
    if (is_array($middleware)) {
        $this->import($middleware, $type);
        return [];
    }
    //返回解析结果
    return [[$middleware, 'handle'], $param ?? null];
}
Nach dem Login kopieren
Eine detaillierte Analyse finden Sie in den obigen Codekommentaren. Das endgültig zurückgegebene Ergebnis wird einer Warteschlange hinzugefügt, indem $ this->queue[$type][] = $middleware; in der Add-Methode ausgeführt wird. Das endgültige Parsing-Ergebnis sieht wahrscheinlich so aus (app/middleware.php entfernt einige Middleware-Kommentare):

ThinkPHP6 lädt Middleware und analysiert mehrere Anwendungen

An diesem Punkt wird die globale Middleware geladen.

2. Parsen mehrerer Anwendungen

Nach dem Laden der Middleware ist der nächste Schritt das Parsen mehrerer Anwendungen (ThinkPHP 6 beginnt mit der Unterstützung des Multianwendungsmodus).

if ($this->multi) {
    $this->parseMultiApp();
}
Nach dem Login kopieren
Beachten Sie, dass der Konstruktor der HTTP-Klasse:

public function __construct(App $app)
{
    $this->app   = $app;
    //多应用解析,通过判断「app」目录下有无「controller」目录,没有就是多应用模式
    $this->multi = is_dir($this->app->getBasePath() . 'controller') ? false : true;
}
Nach dem Login kopieren
Sie können sehen, dass das Programm bestimmt, ob es sich im Mehranwendungsmodus befindet, indem es beurteilt, ob im Verzeichnis „app“ ein „Controller“-Verzeichnis vorhanden ist.

Dann schauen Sie sich die Hauptmethode parseMultiApp an:

protected function parseMultiApp(): void
{
    // 虽然在「Http」的构造函数自动判断过是否开启多应用
    //如果没有controller目录,$this->multi为true,就会来到本方法
    // 接着还要看配置文件是否有配置
    if ($this->app->config->get('app.auto_multi_app', false)) {
        // 自动多应用识别
        $this->bindDomain = false;
        // 获取域名绑定
        $bind = $this->app->config->get('app.domain_bind', []);
        // 如果有域名绑定
        if (!empty($bind)) {
            // 获取当前子域名
            $subDomain = $this->app->request->subDomain();
            $domain    = $this->app->request->host(true);

            //完整域名绑定
            if (isset($bind[$domain])) {
                $appName          = $bind[$domain];
                $this->bindDomain = true;
                //子域名绑定
            } elseif (isset($bind[$subDomain])) {
                $appName          = $bind[$subDomain];
                $this->bindDomain = true;
                //二级泛域名绑定
            } elseif (isset($bind['*'])) {
                $appName          = $bind['*'];
                $this->bindDomain = true;
            }
        }
        //如果没有域名绑定
        if (!$this->bindDomain) {
            //获取别名映射
            $map  = $this->app->config->get('app.app_map', []);
            //获取禁止URL访问目录
            $deny = $this->app->config->get('app.deny_app_list', []);
            //获取当前请求URL的pathinfo信息(含URL后缀)
            // 比如 index/index/index
            $path = $this->app->request->pathinfo();
            // 比如,从index/index/index获取得index
            $name = current(explode('/', $path));
            //解析别名映射
            if (isset($map[$name])) {
                //如果这个别名映射到的是一个闭包
                //这样不知有啥用
                if ($map[$name] instanceof Closure) {
                    $result  = call_user_func_array($map[$name], [$this]);
                    $appName = $result ?: $name;
                    //直接取得应用名
                } else {
                    $appName = $map[$name];
                }
                //$name不为空且$name在$map数组中作为KEY,或者$name是禁止URL方位的目录
            } elseif ($name && (false !== array_search($name, $map) || in_array($name, $deny))) {
                throw new HttpException(404, 'app not exists:' . $name);
            } elseif ($name && isset($map['*'])) {
                $appName = $map['*'];
            } else {
                $appName = $name;
            }

            if ($name) {
                $this->app->request->setRoot('/' . $name);
                $this->app->request->setPathinfo(strpos($path, '/') ? ltrim(strstr($path, '/'), '/') : '');
            }
        }
    } else {
        $appName = $this->name ?: $this->getScriptName();
    }

    $this->loadApp($appName ?: $this->app->config->get('app.default_app', 'index'));
}
Nach dem Login kopieren
Sie können sehen, dass der erste Abschnitt der „Pfadinfo“-Informationen in den Anwendungsnamen geparst wird, z. B. index in index/index/index/. Am Ende der Methode wird auch die Methode „loadApp“ aufgerufen. Der durchgeführte Vorgang ähnelt der Initialisierung der vorherigen Anwendung, mit der Ausnahme, dass sich alle geladenen Dateien im Verzeichnis der Anwendung befinden.

Im Vergleich zur Vorgängerversion scheint ThinkPHP 6 das ursprüngliche Modul in eine Mehrfachanwendung umgewandelt zu haben, da bei Mehrfachanwendungen der Anwendungsname und der vorherige Modulname aus dem ersten Abschnitt der Pfadinformationen analysiert werden Auch im neuen Dokument habe ich den Inhalt des Moduls noch nicht gesehen.

Verwandte Empfehlungen:

Die neuesten 10 Thinkphp-Video-Tutorials

Das obige ist der detaillierte Inhalt vonThinkPHP6 lädt Middleware und analysiert mehrere Anwendungen. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Verwandte Etiketten:
Quelle:segmentfault.com
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage