目次
1. ロード ミドルウェア
loadMiddleware メソッド:
$this->app->middleware を通じて Middleware クラスのインスタンスを取得した後、プログラムは import メソッドを呼び出し、「ミドルウェア」を「app」ディレクトリ。.php」ファイル。ファイルの元の内容は次のとおりです (すべてのコメントは元々コメントアウトされていました):
ミドルウェアをロードした後、次のステップはマルチアプリケーションの解析です (ThinkPHP 6 はマルチアプリケーション モードのサポートを開始します)。
ホームページ PHPフレームワーク ThinkPHP ThinkPHP6 ロードミドルウェアとマルチアプリケーション分析

ThinkPHP6 ロードミドルウェアとマルチアプリケーション分析

Jul 09, 2021 pm 02:48 PM
thinkphp6

1. ロード ミドルウェア

以前に書いた記事では、アプリケーションの初期化、つまり拡張を分析しました。 $this->initialize() の分析。Http クラスの run() メソッドで呼び出される runWithRequest () メソッドのコードの最初の行です。 runWithRequest () メソッドの最初の数行をもう一度見てみましょう。

アプリケーションが初期化されたら、次のステップはミドルウェアを処理することです。

ミドルウェア クラスの初期化

loadMiddleware メソッド:

protected function loadMiddleware(): void
{
    if (is_file($this->app->getBasePath() . 'middleware.php')) {
        $this->app->middleware->import(include $this->app->getBasePath() . 'middleware.php');
    }
}
ログイン後にコピー

は依然として一般的なルーチンであり、$this->app->middleware ファイルを通じてミドルウェアをインスタンス化し、そのミドルウェアを取得します。実例。

ミドルウェアのインポート

$this->app->middleware を通じて Middleware クラスのインスタンスを取得した後、プログラムは import メソッドを呼び出し、「ミドルウェア」を「app」ディレクトリ。.php」ファイル。ファイルの元の内容は次のとおりです (すべてのコメントは元々コメントアウトされていました):

return [
    // 全局请求缓存
    // \think\middleware\CheckRequestCache::class,
    // 多语言加载
     \think\middleware\LoadLangPack::class,
    // Session初始化
    // \think\middleware\SessionInit::class,
    // 页面Trace调试
     \think\middleware\TraceDebug::class,
];
ログイン後にコピー

ミドルウェアがどのようにロードされるかを調べるために、まず 2 つのコメントを削除します。つまり、2 つのミドルウェアを追加します。次に、インポート メソッドを確認します:

public function import(array $middlewares = [], string $type = 'global'): void
{
    foreach ($middlewares as $middleware) {
        $this->add($middleware, $type);
    }
}
ログイン後にコピー

このメソッドは、ミドルウェアの配列とミドルウェア タイプを渡します。デフォルトはグローバルです。キーは内部の add メソッドです。 add メソッドに移動します:

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);
    }
}
ログイン後にコピー

実際、実際の作業は buildMiddleware メソッドです。直接次の場所に移動します:

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];
}
ログイン後にコピー

詳細な分析については、上記のコード コメントを参照してください。最終的に返される結果は、add メソッドで $this->queue\[$type][] = $middleware; を実行し、キューに追加します。最終的な解析結果はおそらく次のようになります (app/middleware.php はいくつかのミドルウェア コメントを削除します):

ThinkPHP6 ロードミドルウェアとマルチアプリケーション分析この時点で、グローバル ミドルウェアがロードされます。

2. マルチアプリケーションの解析

ミドルウェアをロードした後、次のステップはマルチアプリケーションの解析です (ThinkPHP 6 はマルチアプリケーション モードのサポートを開始します)。

if ($this->multi) {
    $this->parseMultiApp();
}
ログイン後にコピー

Http クラスのコンストラクター:

public function __construct(App $app)
{
    $this->app   = $app;
    //多应用解析,通过判断「app」目录下有无「controller」目录,没有就是多应用模式
    $this->multi = is_dir($this->app->getBasePath() . 'controller') ? false : true;
}
ログイン後にコピー

ご覧のとおり、プログラムは、「controller」ディレクトリがあるかどうかを判断することで、マルチアプリケーション モードであるかどうかを判断します。 「app」ディレクトリ。

次に、メイン メソッド parseMultiApp を見てください:

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'));
}
ログイン後にコピー

「pathinfo」情報の最初のセクションが、index/index/ のインデックスなどのアプリケーション名に解析されることがわかります。索引/。メソッドの最後では、loadApp メソッドも呼び出されます。実行される操作は、ロードされるファイルがすべてアプリケーションのディレクトリ内にあることを除いて、前のアプリケーションの初期化と似ています。

以前のバージョンと比較すると、ThinkPHP 6 は元のモジュールをマルチアプリケーションに変換したようです。マルチアプリケーションの場合、アプリケーション名と以前のモジュール名が最初のセクションから解析されるためです。 pathinfo のモジュールのコンテンツは、新しいドキュメントには表示されません。

関連する推奨事項:
最新の 10 件の thinkphp ビデオ チュートリアル

以上がThinkPHP6 ロードミドルウェアとマルチアプリケーション分析の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

Video Face Swap

Video Face Swap

完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)