/** * 执行应用程序 * @access public * @param \think\Request $request Request对象 * @return \think\Response * @throws Exception */ public static function run($request) { // 初始化应用(公共模块) self::initModule(COMMON_MODULE, Config::get()); // 获取配置参数 $config = Config::get(); // 注册根命名空间 if (!empty($config['root_namespace'])) { Loader::addNamespace($config['root_namespace']); } // 加载额外文件 if (!empty($config['extra_file_list'])) { foreach ($config['extra_file_list'] as $file) { $file = strpos($file, '.') ? $file : APP_PATH . $file . EXT; if (is_file($file)) { include_once $file; } } } // 设置系统时区 date_default_timezone_set($config['default_timezone']); // 监听app_init APP_HOOK && Hook::listen('app_init'); // 开启多语言机制 if ($config['lang_switch_on']) { // 获取当前语言 defined('LANG_SET') or define('LANG_SET', Lang::range()); // 加载系统语言包 Lang::load(THINK_PATH . 'lang' . DS . LANG_SET . EXT); if (!APP_MULTI_MODULE) { Lang::load(APP_PATH . 'lang' . DS . LANG_SET . EXT); } } // 获取当前请求的调度信息 $dispatch = $request->dispatch(); if (empty($dispatch)) { // 未指定调度类型 则进行URL路由检测 $dispatch = self::route($request, $config); } // 记录路由信息 APP_DEBUG && Log::record('[ ROUTE ] ' . var_export($dispatch, true), 'info'); // 监听app_begin APP_HOOK && Hook::listen('app_begin', $dispatch); try { switch ($dispatch['type']) { case 'redirect': // 执行重定向跳转 header('Location: ' . $dispatch['url'], true, $dispatch['status']); break; case 'module': // 模块/控制器/操作 $data = self::module($dispatch['module'], $config); break; case 'controller': // 执行控制器操作 $data = Loader::action($dispatch['controller'], $dispatch['params']); break; case 'method': // 执行回调方法 $data = self::invokeMethod($dispatch['method'], $dispatch['params']); break; case 'function': // 规则闭包 $data = self::invokeFunction($dispatch['function'], $dispatch['params']); break; case 'finish': // 已经完成 不再继续执行 break; default: throw new Exception('dispatch type not support', 10008); } } catch (HttpResponseException $exception) { $data = $exception->getResponse(); } // 输出数据到客户端 if (isset($data)) { if ($data instanceof Response) { return $data->send(); } else { // 监听app_end APP_HOOK && Hook::listen('app_end', $data); // 自动响应输出 return Response::instance()->send($data, '', Config::get('response_return')); } } }
/** * @param Exception $exception * @return Response */ protected function convertExceptionToResponse(Exception $exception) { // 收集异常数据 if (APP_DEBUG) { // 调试模式,获取详细的错误信息 $data = ['name' => get_class($exception), 'file' => $exception->getFile(), 'line' => $exception->getLine(), 'message' => $exception->getMessage(), 'trace' => $exception->getTrace(), 'code' => $this->getCode($exception), 'source' => $this->getSourceCode($exception), 'datas' => $this->getExtendData($exception), 'tables' => ['GET Data' => $_GET, 'POST Data' => $_POST, 'Files' => $_FILES, 'Cookies' => $_COOKIE, 'Session' => isset($_SESSION) ? $_SESSION : [], 'Server/Request Data' => $_SERVER, 'Environment Variables' => $_ENV, 'ThinkPHP Constants' => $this->getConst()]]; } else { // 部署模式仅显示 Code 和 Message $data = ['code' => $exception->getCode(), 'message' => $exception->getMessage()]; } if (!APP_DEBUG && !Config::get('show_error_msg')) { // 不显示详细错误信息 $data['message'] = Config::get('error_message'); } ob_start(); ob_implicit_flush(0); extract($data); include Config::get('exception_tmpl'); // 获取并清空缓存 $content = ob_get_clean(); $response = Response::instance()->data($content); if ($exception instanceof HttpException) { $statusCode = $exception->getStatusCode(); //TODO 设置headers 等待response完善 } if (!isset($statusCode)) { $statusCode = 500; } $response->code($statusCode); return $response; }
/** * 输出返回数据 * @access protected * @param mixed $data 要返回的数据 * @param String $type 返回类型 JSON XML * @param integer $code HTTP状态 * @return void */ protected function response($data, $type = '', $code = 200) { return Response::instance()->data($data)->type($type)->code($code); }
/** * 获取当前的Response对象实例 * @return \think\Response */ function response() { return Response::instance(); }
/** * URL重定向 * @access protected * @param string $url 跳转的URL表达式 * @param array|int $params 其它URL参数或http code * @return void */ public function redirect($url, $params = []) { Response::instance()->redirect($url, $params); }