02
08月
2020
执行流程
// 执行应用并响应 Container::get('app')->run()->send();
thinkphp/library/think/App.php
/** * 执行应用程序 * @access public * @return Response * @throws Exception */ public function run() { try { ...... $dispatch = $this->dispatch; if (empty($dispatch)) { // 路由检测 $dispatch = $this->routeCheck()->init(); } // 记录当前调度信息 $this->request->dispatch($dispatch); ...... } catch (HttpResponseException $exception) { ...... } $this->middleware->add(function (Request $request, $next) use ($dispatch, $data) { return is_null($data) ? $dispatch->run() : $data; }); ...... }
$dispatch 获取控制器和操作名,执行路由调度
thinkphp/library/think/route/Dispatch.php
/** * 执行路由调度 * @access public * @return mixed */ public function run() { ...... $data = $this->exec(); ...... }
exec() 通过反射实例化控制器和执行方法
thinkphp/library/think/route/dispatch/Module.php
public function exec() { // 监听module_init $this->app['hook']->listen('module_init'); try { // 实例化控制器 $instance = $this->app->controller($this->controller, $this->rule->getConfig('url_controller_layer'), $this->rule->getConfig('controller_suffix'), $this->rule->getConfig('empty_controller')); } catch (ClassNotFoundException $e) { throw new HttpException(404, 'controller not exists:' . $e->getClass()); } $this->app['middleware']->controller(function (Request $request, $next) use ($instance) { // 获取当前操作名 $action = $this->actionName . $this->rule->getConfig('action_suffix'); // 检查实例中是否可以执行方法 if (is_callable([$instance, $action])) { // 执行操作方法 $call = [$instance, $action]; // 严格获取当前操作方法名 $reflect = new ReflectionMethod($instance, $action); $methodName = $reflect->getName(); $suffix = $this->rule->getConfig('action_suffix'); $actionName = $suffix ? substr($methodName, 0, -strlen($suffix)) : $methodName; $this->request->setAction($actionName); // 自动获取请求变量 $vars = $this->rule->getConfig('url_param_type') ? $this->request->route() : $this->request->param(); $vars = array_merge($vars, $this->param); } elseif (is_callable([$instance, '_empty'])) { // 空操作 $call = [$instance, '_empty']; $vars = [$this->actionName]; $reflect = new ReflectionMethod($instance, '_empty'); } else { // 操作不存在 throw new HttpException(404, 'method not exists:' . get_class($instance) . '->' . $action . '()'); } $this->app['hook']->listen('action_begin', $call); $data = $this->app->invokeReflectMethod($instance, $reflect, $vars); return $this->autoResponse($data); }); return $this->app['middleware']->dispatch($this->request, 'controller'); }
最终获得Response对象,调用send()方法输出数据
thinkphp/library/think/Response.php
/** * 发送数据到客户端 * @access public * @return void * @throws \InvalidArgumentException */ public function send() { // 监听response_send $this->app['hook']->listen('response_send', $this); // 处理输出数据 $data = $this->getContent(); // Trace调试注入 if ('cli' != PHP_SAPI && $this->app['env']->get('app_trace', $this->app->config('app.app_trace'))) { $this->app['debug']->inject($this, $data); } if (200 == $this->code && $this->allowCache) { $cache = $this->app['request']->getCache(); if ($cache) { $this->header['Cache-Control'] = 'max-age=' . $cache[1] . ',must-revalidate'; $this->header['Last-Modified'] = gmdate('D, d M Y H:i:s') . ' GMT'; $this->header['Expires'] = gmdate('D, d M Y H:i:s', $_SERVER['REQUEST_TIME'] + $cache[1]) . ' GMT'; $this->app['cache']->tag($cache[2])->set($cache[0], [$data, $this->header], $cache[1]); } } if (!headers_sent() && !empty($this->header)) { // 发送状态码 http_response_code($this->code); // 发送头部信息 foreach ($this->header as $name => $val) { header($name . (!is_null($val) ? ':' . $val : '')); } } $this->sendData($data); if (function_exists('fastcgi_finish_request')) { // 提高页面响应 fastcgi_finish_request(); } // 监听response_end $this->app['hook']->listen('response_end', $this); // 清空当次请求有效的数据 if (!($this instanceof RedirectResponse)) { $this->app['session']->flush(); } }