ホームページ  >  記事  >  PHPフレームワーク  >  ThinkPHP5 の読み込みプロセスを分析する

ThinkPHP5 の読み込みプロセスを分析する

Guanhui
Guanhui転載
2020-06-11 09:34:482753ブラウズ

ThinkPHP5 の読み込みプロセスを分析する

ThinkPHP のインストール

インストール方法については詳しく説明しません。公式ドキュメント - インストールThinkPHP の詳細については、Composer、Git 経由で zip パッケージをダウンロードするか、ThinkPHP 公式 Web サイトに直接アクセスしてください。私がインストールしたバージョンは 5.0.24

テスト実行

です。

ダウンロードしてインストールした後、プロジェクトのダウンロード ディレクトリがローカル サーバーのプロジェクト ルート ディレクトリにある場合は、ブラウザにアドレス http://localhost/thinkphp5/public/ を直接入力して、デフォルトのようこそページに入ることができます。 ThinkPHP5 (下の図に示すように) ThinkPHP5 が正常にインストールされたことを示します

ThinkPHP5 の読み込みプロセスを分析する

上記のアドレス操作方法に加えて、Apache を介して仮想ホストを構成することもできますまたは Nginx を使用してプロジェクトにアクセスします。興味のある方は、オンラインで特定のチュートリアルを参照し、アクセス用の仮想ホストを構成できます。

では本題に入ります。ThinkPHP5 の実行プロセスを段階的に分析してみましょう...

エントリー ファイル (public\index.php)

public\index.php ファイルを開くと、エントリ ファイルの元のコードが次のとおりであることがわかります。

// [ 应用入口文件 ]
// 定义应用目录
define('APP_PATH', __DIR__ . '/../application/');
// 加载框架引导文件
require __DIR__ . '/../thinkphp/start.php';

エントリ ファイルのコードは非常に単純で、関数 ## を備えたわずか 2 行のコードです。 #

define('APP_PATH', __DIR__ . '/../application/');定义应用目录的常量APP_PATH
require __DIR__ . '/../thinkphp/start.php';加载框架引导文件

上記の 2 つに加えて、関数に加えて、コード行を追加するなど、エントリ ファイル内で独自の定数を定義することもできます。 '); パブリック ディレクトリの定数といくつかの前処理を定義します。

フレームワーク ブート ファイルをロードします (thinkphp\start.php)

同様に、 thinkphp\start.php ファイルには、それほど多くのコードがないことがわかります

namespace think;
// ThinkPHP 引导文件
// 1. 加载基础文件
require __DIR__ . '/base.php';
// 2. 执行应用
App::run()->send();

この短い 2 行のコードから、左側と右側の 2 つのメインがあることがわかります

require __DIR__ . '/base.php';加载基础文件
App::run()->send();执行应用

次の 2 つの主要な点で、これら 2 つの左側と右側が何を行うのか詳しく説明します。

ベース ファイル (thinkphp\base.php) をロードします。

引き続き開きます。 thinkphp\base.php ファイルを開くと、このファイルは最初の 2 つのファイルとは異なり、コードが 2 行しかないことがわかります...

define('THINK_VERSION', '5.0.24');
define('THINK_START_TIME', microtime(true));
define('THINK_START_MEM', memory_get_usage());
define('EXT', '.php');
define('DS', DIRECTORY_SEPARATOR);
defined('THINK_PATH') or define('THINK_PATH', __DIR__ . DS);
define('LIB_PATH', THINK_PATH . 'library' . DS);
define('CORE_PATH', LIB_PATH . 'think' . DS);
define('TRAIT_PATH', LIB_PATH . 'traits' . DS);
defined('APP_PATH') or define('APP_PATH', dirname($_SERVER['SCRIPT_FILENAME']) . DS);
defined('ROOT_PATH') or define('ROOT_PATH', dirname(realpath(APP_PATH)) . DS);
defined('EXTEND_PATH') or define('EXTEND_PATH', ROOT_PATH . 'extend' . DS);
defined('VENDOR_PATH') or define('VENDOR_PATH', ROOT_PATH . 'vendor' . DS);
defined('RUNTIME_PATH') or define('RUNTIME_PATH', ROOT_PATH . 'runtime' . DS);
defined('LOG_PATH') or define('LOG_PATH', RUNTIME_PATH . 'log' . DS);
defined('CACHE_PATH') or define('CACHE_PATH', RUNTIME_PATH . 'cache' . DS);
defined('TEMP_PATH') or define('TEMP_PATH', RUNTIME_PATH . 'temp' . DS);
defined('CONF_PATH') or define('CONF_PATH', APP_PATH); // 配置文件目录
defined('CONF_EXT') or define('CONF_EXT', EXT); // 配置文件后缀
defined('ENV_PREFIX') or define('ENV_PREFIX', 'PHP_'); // 环境变量的配置前缀
// 环境常量
define('IS_CLI', PHP_SAPI == 'cli' ? true : false);
define('IS_WIN', strpos(PHP_OS, 'WIN') !== false);
// 载入Loader类
require CORE_PATH . 'Loader.php';
// 加载环境变量配置文件
if (is_file(ROOT_PATH . '.env')) {
    $env = parse_ini_file(ROOT_PATH . '.env', true);
    foreach ($env as $key => $val) {
        $name = ENV_PREFIX . strtoupper($key);
        if (is_array($val)) {
            foreach ($val as $k => $v) {
                $item = $name . '_' . strtoupper($k);
                putenv("$item=$v");
            }
        } else {
            putenv("$name=$val");
        }
    }
}
// 注册自动加载
\think\Loader::register();
// 注册错误和异常处理机制
\think\Error::register();
// 加载惯例配置文件
\think\Config::set(include THINK_PATH . 'convention' . EXT);

注意深く見てみると、コードには 60 以上あるにもかかわらず、コードの機能は明らかです。主な機能は次の 6 点です。

    Use
  1. define('', '')関数は多くのシステム定数を定義します。 2 つの環境定数
  2. 後で使用するためにローダー クラス (thinkphp\library\think\loader.php) を導入します。
  3. 環境変数構成ファイルをロードします (環境変数構成ファイルの名前は # です) ##.env
  4. 。このファイルは必ずしも存在する必要はありません。実際の開発プロセス中に必要に応じて追加されます)Calling
  5. \think\Loader::register()
  6. 自動登録ロードメカニズムシステム自動ロードの登録
    • Composer
    • 自動ロードサポート名前空間定義の登録
    • クラスライブラリマッピングファイルをロードします。これは
    • runtime
    • cache ディレクトリ classmap.php自動読み込み
    • extend
    • Directory
    に存在します
  7. \think\Error::register() を呼び出す
  8. 例外およびエラー処理メカニズムを登録するカスタム構成ファイル (thinkphp\convention.php) をロードする
  9. #アプリケーションの下で run メソッドを実行します (thinkphp\library\think\App.php)

便宜上、これは run メソッドのコードが少し長いですが、それでも投稿することにします。メソッド全体。叩かないでください。

/**
 * 执行应用程序
 * @access public
 * @param  Request $request 请求对象
 * @return Response
 * @throws Exception
 */
public static function run(Request $request = null)
{
    $request = is_null($request) ? Request::instance() : $request;
    try {
        $config = self::initCommon();
        // 模块/控制器绑定
        if (defined('BIND_MODULE')) {
            BIND_MODULE && Route::bind(BIND_MODULE);
        } elseif ($config['auto_bind_module']) {
            // 入口自动绑定
            $name = pathinfo($request->baseFile(), PATHINFO_FILENAME);
            if ($name && 'index' != $name && is_dir(APP_PATH . $name)) {
                Route::bind($name);
            }
        }
        $request->filter($config['default_filter']);
        // 默认语言
        Lang::range($config['default_lang']);
        // 开启多语言机制 检测当前语言
        $config['lang_switch_on'] && Lang::detect();
        $request->langset(Lang::range());
        // 加载系统语言包
        Lang::load([
            THINK_PATH . 'lang' . DS . $request->langset() . EXT,
            APP_PATH . 'lang' . DS . $request->langset() . EXT,
        ]);
        // 监听 app_dispatch
        Hook::listen('app_dispatch', self::$dispatch);
        // 获取应用调度信息
        $dispatch = self::$dispatch;
        // 未设置调度信息则进行 URL 路由检测
        if (empty($dispatch)) {
            $dispatch = self::routeCheck($request, $config);
        }
        // 记录当前调度信息
        $request->dispatch($dispatch);
        // 记录路由和请求信息
        if (self::$debug) {
            Log::record('[ ROUTE ] ' . var_export($dispatch, true), 'info');
            Log::record('[ HEADER ] ' . var_export($request->header(), true), 'info');
            Log::record('[ PARAM ] ' . var_export($request->param(), true), 'info');
        }
        // 监听 app_begin
        Hook::listen('app_begin', $dispatch);
        // 请求缓存检查
        $request->cache(
            $config['request_cache'],
            $config['request_cache_expire'],
            $config['request_cache_except']
        );
        $data = self::exec($dispatch, $config);
    } catch (HttpResponseException $exception) {
        $data = $exception->getResponse();
    }
    // 清空类的实例化
    Loader::clearInstance();
    // 输出数据到客户端
    if ($data instanceof Response) {
        $response = $data;
    } elseif (!is_null($data)) {
        // 默认自动识别响应输出类型
        $type = $request->isAjax() ?
        Config::get('default_ajax_return') :
        Config::get('default_return_type');
        $response = Response::create($data, $type);
    } else {
        $response = Response::create();
    }
    // 监听 app_end
    Hook::listen('app_end', $response);
    return $response;
}

この約 90 行のコードは一体何をするのですか? コメントの分析に基づくと、主なものは次のとおりです: ステップ関数

  • 最初のステップ: 変数 $request を処理し、それが有効で null ではないことを確認します。
  • 2 番目のステップ: self::initCommon() Call 現在のコントローラーの initCommon() メソッドは、アプリケーションを初期化し、構成情報を返す役割を果たします。
    • Loader::addNamespace(self::$namespace, APP_PATH);Register namespace
    • self::init()このクラスの init() メソッドを呼び出してアプリケーションを初期化します
      • さまざまな構成ファイルをロードします
      • 動作拡張機能をロードしますファイル
      • パブリック ファイルのロード
      • ##言語パックのロード
      ##デバッグ モード関連の処理の適用
    • ##構成アイテムを通じて追加ファイルをロード
    • extra_file_list
    • 関連ファイルをロードする値
    • date_default_timezone_set($config['default_timezone']);
    • システムのタイムゾーンを設定します
    • 呼び出し フック: :listen('app_init ');
    • app_init タグを監視する動作
    • ステップ 3: モジュールまたはコントローラーをバインドするかどうかを決定します
  • ステップ 4:システム言語の設定と読み込み
  • 5 番目のステップ:
  • self::routeCheck($request, $config)
  • ルート検出のために現在のコントローラーのrouteCheck()メソッドを読み込みます
  • Route first アドレス構成の検出。最初にキャッシュ ルートを読み取り、存在しない場合は、ルーティング ファイル構成をインポートします。
      ルーティング構成なし。モジュール/コントローラー/オペレーションを直接解析します。
    • Return module モジュール情報 (モジュール名、制御デバイス名、操作メソッド名)
    • ステップ 6: デバッグ モードを有効にし、ルーティングとリクエスト情報のログを記録します
  • ステップ 7:
  • self:: exec($dispatch, $config)
  • コントローラーで exec() メソッドを呼び出して呼び出し分散を実行します
  • ユーザーのリクエスト タイプに応じて分散処理を実行します。モジュールは次のとおりです。 module type
      Call
    • self::module()
    • モジュールを実行し、モジュールのデプロイと初期化を実行し、現在のコントローラ名とオペレーション名を取得して設定します
    • ステップ 8: クラスのインスタンス化をクリアし、対応する形式でデータをクライアント (つまり、ユーザーに表示される出力インターフェイス) に出力します。
  • 推奨チュートリアル: "
  • PHP
" "

ThinkPHP チュートリアル"

以上がThinkPHP5 の読み込みプロセスを分析するの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はjuejin.imで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。