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 }

 

posted on 2017-06-23 09:56  geek1992  阅读(1204)  评论(0编辑  收藏  举报

导航