框架引导文件源代码 (/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 }