[TOC]
* * * * *
## 1 本節是應用啟動文件(/thinkphp/library/think/App.php)的其他靜態方法分析
**self::initModule()**
~~~
private static function initModule($module, $config)
{
$module = (COMMON_MODULE == $module || !APP_MULTI_MODULE) ? '' : $module . DS;
if (is_file(APP_PATH . $module . 'init' . EXT)) {
include APP_PATH . $module . 'init' . EXT;
} else {
$path = APP_PATH . $module;
$config = Config::load(APP_PATH . $module . 'config' . EXT);
if ($config['app_status']) {
$config = Config::load(APP_PATH . $module . $config['app_status'] . EXT);
}
if ($config['extra_config_list']) {
foreach ($config['extra_config_list'] as $name => $file) {
$file = strpos($file, '.') ? $file : $path . $file . EXT;
Config::load($file, is_string($name) ? $name : pathinfo($file, PATHINFO_FILENAME));
}
}
if (is_file($path . 'alias' . EXT)) {
Loader::addMap(include $path . 'alias' . EXT);
}
if (APP_HOOK && is_file($path . 'tags' . EXT)) {
Hook::import(include $path . 'tags' . EXT);
}
if (is_file($path . 'common' . EXT)) {
include $path . 'common' . EXT;
}
if ($config['lang_switch_on'] && $module) {
Lang::load($path . 'lang' . DS . LANG_SET . EXT);
}
}
}
~~~
**self::initModule()源碼分析**
`$module = (COMMON_MODULE == $module || !APP_MULTI_MODULE) ? '' : $module . DS;`
模塊目錄名稱獲取
~~~
if (is_file(APP_PATH . $module . 'init' . EXT)) {
include APP_PATH . $module . 'init' . EXT;
}
~~~
檢查是否存在模塊對應的初始化入口文件init.php,見使用范例 模塊開發
~~~
$path = APP_PATH . $module;
$config = Config::load(APP_PATH . $module . 'config' . EXT);
~~~
加載模塊的配置文件 見使用范例 模塊開發
~~~
if ($config['app_status']) {
$config = Config::load(APP_PATH . $module . $config['app_status'] . EXT);
}
~~~
加載模塊狀態配置文件 見使用范例 模塊開發
~~~
if ($config['extra_config_list']) {
foreach ($config['extra_config_list'] as $name => $file) {
$file = strpos($file, '.') ? $file : $path . $file . EXT;
Config::load($file, is_string($name) ? $name : pathinfo($file, PATHINFO_FILENAME));
}
}
~~~
加載模塊擴展配置文件 見使用范例模塊開發
~~~
if (is_file($path . 'alias' . EXT)) {
Loader::addMap(include $path . 'alias' . EXT);
}
~~~
加載模塊別名配置文件 見使用范例模塊開發
~~~
if (APP_HOOK && is_file($path . 'tags' . EXT)) {
Hook::import(include $path . 'tags' . EXT);
}
~~~
加載模塊行為擴展文件 見使用范例模塊開發
~~~
if (is_file($path . 'common' . EXT)) {
include $path . 'common' . EXT;
}
~~~
加載模塊公共函數文件 見使用范例模塊開發
~~~
if ($config['lang_switch_on'] && $module) {
Lang::load($path . 'lang' . DS . LANG_SET . EXT);
}
~~~
加載模塊語言包文件 見使用范例模塊開發
* * * * *
* * * * *
**2 self::parsePathinfo()源代碼**
~~~
private static function parsePathinfo(array $config)
{
if (isset($_GET[$config['var_pathinfo']])) {
$_SERVER['PATH_INFO'] = $_GET[$config['var_pathinfo']];
unset($_GET[$config['var_pathinfo']]);
} elseif (IS_CLI) {
// CLI模式下 index.php module/controller/action/params/...
$_SERVER['PATH_INFO'] = isset($_SERVER['argv'][1]) ? $_SERVER['argv'][1] : '';
}
APP_HOOK && Hook::listen('path_info');
if (!isset($_SERVER['PATH_INFO'])) {
foreach ($config['pathinfo_fetch'] as $type) {
if (!empty($_SERVER[$type])) {
$_SERVER['PATH_INFO'] = (0 === strpos($_SERVER[$type], $_SERVER['SCRIPT_NAME'])) ?
substr($_SERVER[$type], strlen($_SERVER['SCRIPT_NAME'])) : $_SERVER[$type];
break;
}
}
}
}
~~~
**self::parsePathinfo()源代碼分析**
~~~
if (isset($_GET[$config['var_pathinfo']])) {
$_SERVER['PATH_INFO'] = $_GET[$config['var_pathinfo']];
unset($_GET[$config['var_pathinfo']]);
} elseif (IS_CLI) {
// CLI模式下 index.php module/controller/action/params/...
$_SERVER['PATH_INFO'] = isset($_SERVER['argv'][1]) ? $_SERVER['argv'][1] : '';
}
~~~
檢查$_GET參數是否包含$config配置的兼容模式參數,
兼容模式參數見附:全局配置文件
如果有 設置$_SERVER['PATH_INFO']為$_GET中兼容模式參數對應的參數的值
并刪除$_GET兼容模式參數
如果沒有檢查模式檢查
檢查是否是CLI模式 然后設置$_SERVER['PATH_INFO']為CLI的$_SERVER['argv'][1]參數
這里的PATH_INFO其實就是調用的文件名稱與參數
` APP_HOOK && Hook::listen('path_info');`
path_info分析回調
~~~
if (!isset($_SERVER['PATH_INFO'])) {
foreach ($config['pathinfo_fetch'] as $type) {
if (!empty($_SERVER[$type])) {
$_SERVER['PATH_INFO'] = (0 === strpos($_SERVER[$type], $_SERVER['SCRIPT_NAME'])) ?
substr($_SERVER[$type], strlen($_SERVER['SCRIPT_NAME'])) : $_SERVER[$type];
break;
}
}
}
~~~
如果上面獲取PATH_INFO失敗
那么從配置信息$config['pathinfp_fetch']中依次讀取PATH_INFP信息
經過上面調用獲取了全局變量$_SERVER['PATH_INFO']的值,這個值在下面的self::route()中會用到
* * * * *
* * * * *
**3 self::route()源代碼**
~~~
public static function route(array $config)
{
self::parsePathinfo($config);
if (empty($_SERVER['PATH_INFO'])) {
$_SERVER['PATH_INFO'] = '';
define('__INFO__', '');
define('__EXT__', '');
} else {
$_SERVER['PATH_INFO'] = trim($_SERVER['PATH_INFO'], '/');
define('__INFO__', $_SERVER['PATH_INFO']);
define('__EXT__', strtolower(pathinfo($_SERVER['PATH_INFO'], PATHINFO_EXTENSION)));
if ($config['url_deny_suffix'] && preg_match('/\.(' . $config['url_deny_suffix'] . ')$/i', __INFO__)) {
throw new Exception('url suffix deny');
}
$_SERVER['PATH_INFO'] = preg_replace($config['url_html_suffix'] ? '/\.(' . trim($config['url_html_suffix'], '.') . ')$/i' : '/\.' . __EXT__ . '$/i', '', __INFO__);
}
$depr = $config['pathinfo_depr'];
$result = false;
if (APP_ROUTE_ON && !empty($config['url_route_on'])) {
if (!empty($config['route'])) {
Route::register($config['route']);
}
$result = Route::check($_SERVER['PATH_INFO'], $depr, !IS_CLI ? $config['url_domain_deploy'] : false);
if (APP_ROUTE_MUST && false === $result && $config['url_route_must']) {
throw new Exception('route not define ');
}
}
if (false === $result) {
$result = Route::parseUrl($_SERVER['PATH_INFO'], $depr);
}
self::dispatch($result);
}
~~~
**self::route()源代碼分析**
`self::parsePathinfo($config);`
調用上面的self::parsePathinfo()獲取$_SERVER['PATH_INFO']的值
~~~
$_SERVER['PATH_INFO'] = '';
define('__INFO__', '');
define('__EXT__', '');
~~~
如果$_SERVER['PATH_INFO']為空
設置`__INFO__ __EXT__`全局變量為空
~~~
$_SERVER['PATH_INFO'] = trim($_SERVER['PATH_INFO'], '/');
define('__INFO__', $_SERVER['PATH_INFO']);
define('__EXT__', strtolower(pathinfo($_SERVER['PATH_INFO'], PATHINFO_EXTENSION)));
if ($config['url_deny_suffix'] && preg_match('/\.(' . $config['url_deny_suffix'] . ')$/i', __INFO__)) {
throw new Exception('url suffix deny');
}
$_SERVER['PATH_INFO'] = preg_replace($config['url_html_suffix'] ? '/\.(' . trim($config['url_html_suffix'], '.') . ')$/i' : '/\.' . __EXT__ . '$/i', '', __INFO__);
~~~
如果$_SERVER['PATH_INFO']為空
設置`__INFO__ __EXT__`為$_SERVER['PATH_INFO']的相應值。
并檢查是否禁用相應的后綴請求 見使用范例 禁用URL后綴
接著去除正常的Url后綴???待分析
`$depr = $config['pathinfo_depr'];`
獲取配置的pathinfo_depr,
~~~
if (APP_ROUTE_ON && !empty($config['url_route_on'])) {
}
~~~
檢查全局變量APP_ROUTE_ON 是否開啟路由檢測
全局變量設置見 [附:全局變量文件](http://www.hmoore.net/zmwtp/tp5/119430)
如果開啟
~~~
if (!empty($config['route'])) {
Route::register($config['route']);
}
~~~
將配置中的路由添加到全局路由定義
全局路由定義見 [附:全局路由文件](http://www.hmoore.net/zmwtp/tp5/119438)
`$result = Route::check($_SERVER['PATH_INFO'], $depr, !IS_CLI ? $config['url_domain_deploy'] : false);`
檢查路由 ???待分析
~~~
if (APP_ROUTE_MUST && false === $result && $config['url_route_must']) {
throw new Exception('route not define ');
}
~~~
路由檢測結果分析
~~~
if (false === $result) {
$result = Route::parseUrl($_SERVER['PATH_INFO'], $depr);
}
~~~
路由url分析 見 [附:全局路由文件](http://www.hmoore.net/zmwtp/tp5/119438)
`self::dispatch($result);`
注冊路由分析結果到app調度類型$dispatch
調度類型的使用見 [應用調度分析](http://www.hmoore.net/zmwtp/tp5/119428)
## 3 總結
**initModule() 模塊的初始化實現**
在系統主流程App::run()中有兩處調用,
一處是App::run()剛開始總的公共模塊初始化
self::initModule(COMMON_MODULE,Config::get())
一處是App::module()中的應用模塊初始化
self::initModule(MODULE_NAME, $config);
**parsePathinfo() 獲取請求信息**
**route() 根據請求信息進行路由分派**
其他的函數包括
run() 應用啟動流程 見 [應用啟動文件](http://www.hmoore.net/zmwtp/tp5/119426)
invokeFunction() 調度回調函數 見 [應用調度分析](http://www.hmoore.net/zmwtp/tp5/119428)
invokeMethod() 調度回調方法 見 [應用調度分析](http://www.hmoore.net/zmwtp/tp5/119428)
bindParams() 調度參數合成 見 [應用調度分析](http://www.hmoore.net/zmwtp/tp5/119428)
module() 調度回調模塊 見 [應用調度分析](http://www.hmoore.net/zmwtp/tp5/119428)
dispathc() 調度注冊見[應用調度分析](http://www.hmoore.net/zmwtp/tp5/119428)
- 更新記錄
- 概述
- 文件索引
- 函數索引
- 章節格式
- 框架流程
- 前:章節說明
- 主:(index.php)入口
- 主:(start.php)框架引導
- 主:(App.php)應用啟動
- 主:(App.php)應用調度
- C:(Controller.php)應用控制器
- M:(Model.php)數據模型
- V:(View.php)視圖對象
- 附:(App.php)應用啟動
- 附:(base.php)全局變量
- 附:(common.php)模式配置
- 附:(convention.php)全局配置
- 附:(Loader.php)自動加載器
- 附:(Build.php)自動生成
- 附:(Hook.php)監聽回調
- 附:(Route.php)全局路由
- 附:(Response.php)數據輸出
- 附:(Log.php)日志記錄
- 附:(Exception.php)異常處理
- 框架工具
- 另:(helper.php)輔助函數
- 另:(Cache.php)數據緩存
- 另:(Cookie.php)cookie操作
- 另:(Console.php)控制臺
- 另:(Debug.php)開發調試
- 另:(Error.php)錯誤處理
- 另:(Url.php)Url操作文件
- 另:(Loader.php)加載器實例化
- 另:(Input.php)數據輸入
- 另:(Lang.php)語言包管理
- 另:(ORM.php)ORM基類
- 另:(Process.php)進程管理
- 另:(Session.php)session操作
- 另:(Template.php)模板解析
- 框架驅動
- D:(\config)配置解析
- D:(\controller)控制器擴展
- D:(\model)模型擴展
- D:(\db)數據庫驅動
- D:(\view)模板解析
- D:(\template)模板標簽庫
- D:(\session)session驅動
- D:(\cache)緩存驅動
- D:(\console)控制臺
- D:(\process)進程擴展
- T:(\traits)Trait目錄
- D:(\exception)異常實現
- D:(\log)日志驅動
- 使用范例
- 服務器與框架的安裝
- 控制器操作
- 數據模型操作
- 視圖渲染控制
- MVC開發初探
- 模塊開發
- 入口文件定義全局變量
- 運行模式開發
- 框架配置
- 自動生成應用
- 事件與插件注冊
- 路由規則注冊
- 輸出控制
- 多種應用組織
- 綜合應用
- tp框架整合后臺auto架構快速開發
- 基礎原理
- php默認全局變量
- php的魔術方法
- php命名空間
- php的自動加載
- php的composer
- php的反射
- php的trait機制
- php設計模式
- php的系統時區
- php的異常錯誤
- php的輸出控制
- php的正則表達式
- php的閉包函數
- php的會話控制
- php的接口
- php的PDO
- php的字符串操作
- php的curl
- 框架心得
- 心:整體結構
- 心:配置詳解
- 心:加載器詳解
- 心:輸入輸出詳解
- 心:url路由詳解
- 心:模板詳解
- 心:模型詳解
- 心:日志詳解
- 心:緩存詳解
- 心:控制臺詳解
- 框架更新
- 4.20(驗證類,助手函數)
- 4.27(新模型Model功能)
- 5.4(新數據庫驅動)
- 7.28(自動加載)