從請求入口文件開始,到響應組件發送結果給用戶瀏覽器的過程簡要分析。php
從入口文件進入,直接看關鍵點,分析application
的啓動流程web
$config = require __DIR__.'/../config/web.php'; (new yii\web\Application($config))->run();
首先進入yii\web\Application
類
裏面沒有構造函數,即找到父級類\yii\base\Application
數組
public function __construct($config = []) { // 保存當前啓動的application實例,交給Yii::$app Yii::$app = $this; static::setInstance($this); $this->state = self::STATE_BEGIN; $this->preInit($config); // 加載異常處理,這塊比較深,後面再擴展。 $this->registerErrorHandler($config); Component::__construct($config); }
咱們看一下static::setInstance($this);
指向到了yii\base\Module
瀏覽器
public static function setInstance($instance) { // 將當前實例加入Yii::$app->loadedModules['yii\web\Application']數組中 if ($instance === null) { unset(Yii::$app->loadedModules[get_called_class()]); } else { Yii::$app->loadedModules[get_class($instance)] = $instance; } }
這裏主要是後面使用,好比module裏,經過self::getInstance()獲取App對象,相似於Yii::$app。(可後面再深刻)app
接下來看$this->preInit($config);
這裏是加載配置文件的框架信息,如:設置別名,設置框架路徑等等,最重要的是加載默認組件框架
foreach ($this->coreComponents() as $id => $component) { if (!isset($config['components'][$id])) { $config['components'][$id] = $component; } elseif (is_array($config['components'][$id]) && !isset($config['components'][$id]['class'])) { $config['components'][$id]['class'] = $component['class']; } }
再接着是Component::__construct($config);
yii
public function __construct($config = []) { if (!empty($config)) { Yii::configure($this, $config);//將配置文件裏面的全部配置信息 本地變量化 } $this->init(); // 取出控制器的命名空間(路徑) }
到這裏爲止,第一部分已經執行完了,開始執行$application->run()
函數
public function run() { try { $this->state = self::STATE_BEFORE_REQUEST; //加載事件函數的。相似於狗子,後面再深刻分析。 $this->trigger(self::EVENT_BEFORE_REQUEST); $this->state = self::STATE_HANDLING_REQUEST; // 重中之重-加載控制器 $response = $this->handleRequest($this->getRequest()); $this->state = self::STATE_AFTER_REQUEST; $this->trigger(self::EVENT_AFTER_REQUEST);//加載事件函數 $this->state = self::STATE_SENDING_RESPONSE; $response->send();//將頁面內容輸出 $this->state = self::STATE_END; return $response->exitStatus; } catch (ExitException $e) { $this->end($e->statusCode, isset($response) ? $response : null); return $e->statusCode; } }
咱們來看下$response = $this->handleRequest($this->getRequest());
ui
public function handleRequest($request) { if (empty($this->catchAll)) { try { list($route, $params) = $request->resolve(); } catch (UrlNormalizerRedirectException $e) { $url = $e->url; if (is_array($url)) { if (isset($url[0])) { // ensure the route is absolute $url[0] = '/' . ltrim($url[0], '/'); } $url += $request->getQueryParams(); } return $this->getResponse()->redirect(Url::to($url, $e->scheme), $e->statusCode); } } else { $route = $this->catchAll[0]; $params = $this->catchAll; unset($params[0]); } try { Yii::debug("Route requested: '$route'", __METHOD__); $this->requestedRoute = $route; $result = $this->runAction($route, $params); if ($result instanceof Response) { return $result; } $response = $this->getResponse(); if ($result !== null) { $response->data = $result; } return $response; } catch (InvalidRouteException $e) { throw new NotFoundHttpException(Yii::t('yii', 'Page not found.'), $e->getCode(), $e); } }
咱們再看看這句指向:\yii\base\Module
的runAction
this
public function runAction($route, $params = []) { $parts = $this->createController($route); if (is_array($parts)) { /* @var $controller Controller */ list($controller, $actionID) = $parts; $oldController = Yii::$app->controller; Yii::$app->controller = $controller; $result = $controller->runAction($actionID, $params); if ($oldController !== null) { Yii::$app->controller = $oldController; } return $result; } $id = $this->getUniqueId(); throw new InvalidRouteException('Unable to resolve the request "' . ($id === '' ? $route : $id . '/' . $route) . '".'); }
最後是$response->send();
public function send() { if ($this->isSent) { return; } $this->trigger(self::EVENT_BEFORE_SEND); //取得$response的format 再得到format對象的實例執行 format方法(header設置Content-Type) $this->prepare(); $this->trigger(self::EVENT_AFTER_PREPARE); $this->sendHeaders(); $this->sendContent(); $this->trigger(self::EVENT_AFTER_SEND); $this->isSent = true; }
yii給出的運行機制概述和示意圖來描述應用是如何處理一個請求的。