ThinkPHP のインストール
詳しくは説明しませんインストール方法については、公式ドキュメント - ThinkPHP のインストールは非常に完了しています。Composer、Git、または ThinkPHP 公式 Web サイトから直接 zip パッケージをダウンロードできます。私がインストールしたバージョンは 5.0.24
Test run
ダウンロードとインストールが完了しました。最後に、プロジェクトのダウンロード ディレクトリがローカル サーバーのプロジェクト ルート ディレクトリにある場合は、アドレス http://localhost/thinkphp5/public/## を直接入力できます。 # 以下の図に示すように、ブラウザで ThinkPHP5 のデフォルトのようこそページに入ります。これは、ThinkPHP5 が正常にインストールされたことを意味します
上記の方法でアドレスを実行することに加えて、Apache または Nginx を通じてアドレスを実行することもできます プロジェクトにアクセスするように仮想ホストを構成します。興味がある場合は、特定のチュートリアルをオンラインで確認し、アクセス用に仮想ホストを構成できます。 では本題に入ります。ThinkPHP5 の実行プロセスを段階的に分析してみましょう... エントリー ファイル (publicindex.php) Open
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 つの関数に加えて、エントリ ファイルに独自の定数を定義することもできます。コード行を追加します。
パブリック ディレクトリの定数と前処理などを定義します。フレームワークをロードします。ブート ファイル (thinkphpstart.php)
同様に、ファイルの後に
thinkphp\start.php と入力すると、多くのコードがないことがわかります<pre class="brush:php;toolbar:false">namespace think;
// ThinkPHP 引导文件
// 1. 加载基础文件
require __DIR__ . '/base.php';
// 2. 执行应用
App::run()->send();</pre>
これら 2 つの短い内容からコード行を見ると、左右に 2 つのメインがあることがわかります。
- require __DIR__ . '/base.php';
- ベース ファイルのロード
- アプリケーションを実行します
基本ファイル (thinkphpbase.php) をロードします
続きましょう
thinkphp\base.php ファイルを開くと、このファイルには以前のような 2 行のコードしか含まれていないことがわかります。 2 つのファイル...<pre class="brush:php;toolbar:false">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);</pre>
よく見てみると、コードは 6 行以上ありますが、コードの機能は明らかです。主な機能は次の 6 点です
- define('', '')
- 関数を使用して、多くのシステム定数を定義します。さらに 2 つの環境定数を定義します。
後で使用するためにローダー クラス (thinkphplibrarythinkloader.php) を導入します
- 環境変数設定ファイルをロードします (環境変数設定ファイルの名前は .env
- です。このファイルは必ずしも存在するわけではありません。実際の開発プロセス中に必要に応じて追加されます)
- \think\Loader::register()
自動読み込みメカニズムの登録
登録システムの自動読み込み- Composer
- 自動読み込みサポート
登録名前空間定義
- クラス ライブラリ マッピング ファイルを読み込み、 runtime
- キャッシュ ディレクトリに存在します
classmap.php
自動的にロード
extend - ディレクトリ
例外およびエラー処理メカニズムを登録 - #規約設定ファイルをロードする (thinkphpconvention.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() 現在のコントローラーで initCommon() メソッドを呼び出します。このメソッドは、アプリケーションを初期化し、構成情報を返す役割を果たします -
名前空間の登録Loader::addNamespace(self::$namespace, APP_PATH) ;
-
self::init()
このクラスの init () メソッドを呼び出してアプリケーションを初期化します - さまざまな構成ファイルのロード
- 動作拡張ファイルのロード
- パブリック ファイルのロード
- 言語パックのロード
デバッグ モード関連の処理を適用します。- 追加ファイルをロードし、構成項目の値を介して関連ファイルをロードします。
- extra_file_list
- date_default_timezone_set($config['default_timezone'] );
システムのタイムゾーンを設定します
呼び出し - Hook::listen('app_init');
app_init タグをリッスンする動作
-
- ステップ 4: システム言語の設定と読み込み
- ステップ 5:
- self::routeCheck($request , $config)
ルート検出のために現在のコントローラーのrouteCheck()メソッドをロードします
最初にルーティング アドレス構成の検出を実行し、最初にキャッシュされたルートを読み取り、ルーティング ファイル構成が存在する場合はそれをインポートします。存在しません- ルーティング構成はありません。モジュール/コントローラー/操作を直接解析します #モジュールモジュール情報 (モジュール名、コントローラー名、および操作メソッド名)を返します
- ステップ 6: デバッグ モードを有効にし、ルーティングとリクエスト情報のログを記録します。
- ステップ 7: self::exec($dispatch, $config)
- コントローラー exec()メソッドで呼び出し分散を実行
ユーザーリクエストの種類に応じて分散処理を行うここにモジュール module type
- Call
- self::module () 実行モジュール、モジュールのデプロイと初期化を実行し、現在のコントローラー名と操作名を取得して設定します
- 概要