多应用+插件架构,代码干净,支持一键云编译,码云点赞13K star,4.8-4.12 预售价格198元 广告
[TOC] * * * * * #1 启动概述 * 启动的总流程按照文件分为三步 * 1 请求入口(public/index.php) * 2 框架启动(thinkphp/start.php) * 3 应用启动 (thinkphp/library/App.php) #2 入口文件(public/index.php) ~~~ // 定义应用目录 define('APP_PATH', __DIR__ . '/../application/'); // 加载框架引导文件 require __DIR__ . '/../thinkphp/start.php'; ~~~ > 默认的入口文件在public/index.php >> 主要定义应用目录,加载框架引导文件(thinkphp/start.php) #3 框架启动(thinkphp/start.php) ## 3-1 框架引导(thinkphp/start.php) ~~~ // 加载基础文件 require __DIR__ . '/base.php'; // 执行应用 App::run()->send(); ~~~ > 框架引导文件(thinkphp/start.php) >>主要用来启动框架 >>按照涉及的文件分为以下三步 >>1 定义全局变量与注册自动加载 >>2 加载默认配置 >>3 启动应用 ## 3-2 定义全局常量(thinkphp/base.php) ~~~ define('THINK_VERSION', '5.0.0'); 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(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); ~~~ >>基础文件(thinkphp/base.php) >>开始部分定义了框架的全局常量 >>包括框架的运行信息,目录组织,运行环境等 ## 3-3 注册自动加载(thinkphp/base.php) ~~~ // 载入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(); ~~~ >> 基础文件(thinkphp/base.php) >> 中间部分加载环境配置, >> 启动自动加载 >> 注册自定义错误与异常处理 ## 3-4 加载框架默认配置(thinkphp/convention.php) ~~~ \think\Config::set(include THINK_PATH . 'convention' . EXT); ~~~ >>基础文件(thinkphp/base.php) >>最后加载框架默认配置 ## 3-5 框架默认配置(thinkphp/convention.php) ~~~ 应用设置 模块设置 URL设置 模板设置 异常及错误设置 日志设置 Trace设置 缓存设置 会话设置 Cookie设置 数据库设置 分页配置 ~~~ >>以数组形式实现框架默认配置 >>相关配置信息可以在应用目录(application/)中进行覆盖 #4 应用启动(thinkphp/library/App.php) ## 4-1 请求分析(App.php->run()) ~~~ App.php; public static function run(Request $request = null) is_null($request) && $request = Request::instance(); $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']); 。。。。。。 } ~~~ >> 应用启动的请求分析 >> 首先 创建请求对象(Request) >> 然后 解析请求的模块信息 >> 最后 过滤请求信息 ## 4-2 应用调度(App.php->run()) ~~~ App.php; public static function run(Request $request = null) 。。。。。。 try { // 开启多语言机制 if ($config['lang_switch_on']) { // 获取当前语言 $request->langset(Lang::detect()); // 加载系统语言包 Lang::load(THINK_PATH . 'lang' . DS . $request->langset() . EXT); if (!$config['app_multi_module']) { Lang::load(APP_PATH . 'lang' . DS . $request->langset() . EXT); } } // 获取应用调度信息 $dispatch = self::$dispatch; if (empty($dispatch)) { // 进行URL路由检测 $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); switch ($dispatch['type']) { case 'redirect': // 执行重定向跳转 $data = Response::create($dispatch['url'], 'redirect')->code($dispatch['status']); break; case 'module': // 模块/控制器/操作 $data = self::module($dispatch['module'], $config, isset($dispatch['convert']) ? $dispatch['convert'] : null); break; case 'controller': // 执行控制器操作 $data = Loader::action($dispatch['controller']); break; case 'method': // 执行回调方法 $data = self::invokeMethod($dispatch['method']); break; case 'function': // 执行闭包 $data = self::invokeFunction($dispatch['function']); break; case 'response': $data = $dispatch['response']; break; default: throw new \InvalidArgumentException('dispatch type not support'); } } catch (HttpResponseException $exception) { $data = $exception->getResponse(); } 。。。。。。 } ~~~ >>应用启动的应用调度 >>首先 检查语言配置 >>然后 路由解析获取调度信息 >>最后 根据调度类型执行不同类型应用 ## 4-3 数据输出(App.php->run()) ~~~ App.php; public static function run(Request $request = null) // 清空类的实例化 Loader::clearInstance(); // 输出数据到客户端 if ($data instanceof Response) { $response = $data; } elseif (!is_null($data)) { // 默认自动识别响应输出类型 $isAjax = $request->isAjax(); $type = $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; 。。。。。。 } ~~~ >>应用逻辑执行完后, >>首先 清空应用执行过程创建的对象 >>然后 根据应用执行后返回的数据创建响应对象(Response) >>最后 调用相应对象的send()输出数据到客户端(start.php文件中)