thinkphp5 源碼分析三 應用啓動

框架引導文件源代碼 (/thinkphp/start.php)

// 執行應用
App::run()->send();

1. 應用啓動(/thinkphp/library/think/App.php)

//初始化請求實例
is_null($request) && $request = Request::instance();

2. 添加APP命名空間(app => /application)

1  //添加app命名空間
2  if (defined('APP_NAMESPACE')) {
3  self::$namespace = APP_NAMESPACE;
4  }
5  Loader::addNamespace(self::$namespace, APP_PATH);

3. 初始化應用

// 初始化應用
 $config       = self::init();
 1   // 定位模塊目錄
 2   $module = $module ? $module . DS : '';
 3 
 4   // 加載初始化文件
 5   if (is_file(APP_PATH . $module . 'init' . EXT)) {
 6     include APP_PATH . $module . 'init' . EXT;
 7   } elseif (is_file(RUNTIME_PATH . $module . 'init' . EXT)) {
 8     include RUNTIME_PATH . $module . 'init' . EXT;
 9   } else {
10   $path = APP_PATH . $module;
11   // 加載模塊配置
12   $config = Config::load(CONF_PATH . $module . 'config' . CONF_EXT);
13 
14   // 讀取數據庫配置文件
15   $filename = CONF_PATH . $module . 'database' . CONF_EXT;
16   Config::load($filename, 'database');
17   // 讀取擴展配置文件
18   if (is_dir(CONF_PATH . $module . 'extra')) {
19      $dir   = CONF_PATH . $module . 'extra';
20      $files = scandir($dir);
21      foreach ($files as $file) {
22         if (strpos($file, CONF_EXT)) {
23              $filename = $dir . DS . $file;
24              Config::load($filename, pathinfo($file, PATHINFO_FILENAME));
25           }
26       }
27    }
28    // 加載應用狀態配置
29    if ($config['app_status']) {
30        $config = Config::load(CONF_PATH . $module . $config['app_status'] . CONF_EXT);
31      }
32    // 加載行爲擴展文件(中間件 權限控制能夠配置加在這裏)
33    if (is_file(CONF_PATH . $module . 'tags' . EXT)) {
34        Hook::import(include CONF_PATH . $module . 'tags' . EXT);
35     }
36     // 加載公共文件
37     if (is_file($path . 'common' . EXT)) {
38         include $path . 'common' . EXT;
39     }
40 
41     // 加載當前模塊語言包
42     if ($module) {
43        Lang::load($path . 'lang' . DS . Request::instance()->langset() . EXT);
44     }

4. 綁定模塊、控制器

 1 if (defined('BIND_MODULE')) {
 2      // 模塊/控制器綁定
 3      BIND_MODULE && Route::bind(BIND_MODULE);
 4 } elseif ($config['auto_bind_module']) {
 5        // 入口自動綁定
 6     $name = pathinfo($request->baseFile(), PATHINFO_FILENAME);
 7     if ($name && 'index' != $name && is_dir(APP_PATH . $name)) {
 8             Route::bind($name);
 9      }
10 }    

5. 加載語言

 1 // 默認語言
 2 Lang::range($config['default_lang']);
 3 if ($config['lang_switch_on']) {
 4     // 開啓多語言機制 檢測當前語言
 5     Lang::detect();
 6 }
 7 $request->langset(Lang::range());
 8 
 9 // 加載系統語言包
10 Lang::load([
11     THINK_PATH . 'lang' . DS . $request->langset() . EXT,
12     APP_PATH . 'lang' . DS . $request->langset() . EXT,
13 ]);

6. 獲取應用調度信息

1 // 獲取應用調度信息
2 $dispatch = self::$dispatch;
3 
4 if (empty($dispatch)) {
5     // 進行URL路由檢測
6     $dispatch = self::routeCheck($request, $config);
7 }

7. 記錄路由和請求信息

1 // 記錄路由和請求信息
2 if (self::$debug) {
3     Log::record('[ ROUTE ] ' . var_export($dispatch, true), 'info');
4     Log::record('[ HEADER ] ' . var_export($request->header(), true), 'info');
5     Log::record('[ PARAM ] ' . var_export($request->param(), true), 'info');
6 }

8. 構造頁面輸出 (查看thinkphp5 源碼分析四 數據構造)

1 // 請求緩存檢查
2 $request->cache($config['request_cache'], $config['request_cache_expire'], $config['request_cache_except']);
3 // 查看thinkphp5 源碼分析四 數據構造
4 $data = self::exec($dispatch, $config);

 

9. 清空Loader類的實例化

1 // 清空Loader類的實例化
2  Loader::clearInstance();

10. 輸出數據

 1  // 輸出數據到客戶端
 2 if ($data instanceof Response) {
 3     // 是不是 response 的實例
 4     $response = $data;
 5 } elseif (!is_null($data)) {
 6     // 默認自動識別響應輸出類型
 7     $isAjax   = $request->isAjax();
 8     $type     = $isAjax ? Config::get('default_ajax_return') : Config::get('default_return_type');
 9     $response = Response::create($data, $type);
10 } else {
11     $response = Response::create();
12 }

11. 發送數據到客戶端

 1 // 處理輸出數據
 2 $data = $this->getContent();
 3 // Trace調試注入
 4 if (Env::get('app_trace', Config::get('app_trace'))) {
 5     Debug::inject($this, $data);
 6 }
 7 
 8 if (200 == $this->code) {
 9     $cache = Request::instance()->getCache();
10 
11     if ($cache) {
12         $this->header['Cache-Control'] = 'max-age=' . $cache[1] . ',must-revalidate';
13         $this->header['Last-Modified'] = gmdate('D, d M Y H:i:s') . ' GMT';
14         $this->header['Expires']       = gmdate('D, d M Y H:i:s', $_SERVER['REQUEST_TIME'] + $cache[1]) . ' GMT';
15         Cache::set($cache[0], [$data, $this->header], $cache[1]);
16     }
17 }
18 
19 if (!headers_sent() && !empty($this->header)) {
20     // 發送狀態碼
21     http_response_code($this->code);
22     // 發送頭部信息
23     foreach ($this->header as $name => $val) {
24         if (is_null($val)) {
25             header($name);
26         } else {
27             header($name . ':' . $val);
28         }
29     }
30 }
31 
32 //輸出數據
33 echo $data;
34 
35 if (function_exists('fastcgi_finish_request')) {
36     // 提升頁面響應
37     fastcgi_finish_request();
38 }
39 
40 // 監聽response_end
41 Hook::listen('response_end', $this);
42 
43 // 清空當次請求有效的數據
44 if (!($this instanceof RedirectResponse)) {
45     //清空SESSION
46     Session::flush();
47 }
相關文章
相關標籤/搜索