Application是所有應用程序類的基類,接下來了解一下它的源碼。yii2\base\Application.php。
1 <?php
2 /**
3 * @link http://www.yiiframework.com/
4 * @copyright Copyright (c) 2008 Yii Software LLC
5 * @license http://www.yiiframework.com/license/
6 */
7
8 namespace yii\base;
9
10 use Yii;
11
12 /**
13 * Application is the base class for all application classes.
14 * 是所有應用程序類的基類
15 * @property \yii\web\AssetManager $assetManager The asset manager application component. This property is
16 * read-only.資產管理器應用組件,只讀
17 * @property \yii\rbac\ManagerInterface $authManager The auth manager application component. Null is returned
18 * if auth manager is not configured. This property is read-only.認證管理器應用程序組件。未配置返回null,只讀
19 * @property string $basePath The root directory of the application. 應用程序的根目錄。
20 * @property \yii\caching\Cache $cache The cache application component. Null if the component is not enabled.
21 * This property is read-only.緩存應用程序組件。
22 * @property \yii\db\Connection $db The database connection. This property is read-only.數據庫連接。
23 * @property \yii\web\ErrorHandler|\yii\console\ErrorHandler $errorHandler The error handler application
24 * component. This property is read-only.錯誤處理程序應用程序組件
25 * @property \yii\i18n\Formatter $formatter The formatter application component. This property is read-only.
26 * 格式化程序的應用程序組件。
27 * @property \yii\i18n\I18N $i18n The internationalization application component. This property is read-only.
28 * 國際化應用組件。
29 * @property \yii\log\Dispatcher $log The log dispatcher application component. This property is read-only.
30 * 日志調度程序組件。
31 * @property \yii\mail\MailerInterface $mailer The mailer application component. This property is read-only.
32 * 郵件應用程序組件。
33 * @property \yii\web\Request|\yii\console\Request $request The request component. This property is read-only.
34 * 請求組件。
35 * @property \yii\web\Response|\yii\console\Response $response The response component. This property is
36 * read-only.反應元件。
37 * @property string $runtimePath The directory that stores runtime files. Defaults to the "runtime"
38 * subdirectory under [[basePath]].存儲運行時文件的目錄。
39 * @property \yii\base\Security $security The security application component. This property is read-only.
40 * 安全應用組件。
41 * @property string $timeZone The time zone used by this application.該應用程序使用的時區。
42 * @property string $uniqueId The unique ID of the module. This property is read-only.模塊的唯一標識。
43 * @property \yii\web\UrlManager $urlManager The URL manager for this application. This property is read-only.
44 * 此應用程序的網址管理器。
45 * @property string $vendorPath The directory that stores vendor files. Defaults to "vendor" directory under
46 * [[basePath]].存儲供應商文件的目錄。
47 * @property View|\yii\web\View $view The view application component that is used to render various view
48 * files. This property is read-only.用於呈現各種視圖文件的視圖應用程序組件
49 *
50 * @author Qiang Xue <qiang.xue@gmail.com>
51 * @since 2.0
52 */
53 abstract class Application extends Module
54 {
55 /**
56 * @event Event an event raised before the application starts to handle a request.
57 * 在應用程序開始處理請求之前提出的事件。
58 */
59 const EVENT_BEFORE_REQUEST = 'beforeRequest';
60 /**
61 * @event Event an event raised after the application successfully handles a request (before the response is sent out).
62 * 該應用程序成功處理請求後提出的事件
63 */
64 const EVENT_AFTER_REQUEST = 'afterRequest';
65 /**
66 * Application state used by [[state]]: application just started.
67 * [[state]]適用狀態:剛開始應用
68 */
69 const STATE_BEGIN = 0;
70 /**
71 * Application state used by [[state]]: application is initializing.
72 * [[state]]應用程序狀態:應用程序初始化。
73 */
74 const STATE_INIT = 1;
75 /**
76 * Application state used by [[state]]: application is triggering [[EVENT_BEFORE_REQUEST]].
77 * [[state]]應用程序狀態:應用觸發[[EVENT_BEFORE_REQUEST]]
78 */
79 const STATE_BEFORE_REQUEST = 2;
80 /**
81 * Application state used by [[state]]: application is handling the request.
82 * [[state]]應用程序狀態:應用程序處理請求。
83 */
84 const STATE_HANDLING_REQUEST = 3;
85 /**
86 * Application state used by [[state]]: application is triggering [[EVENT_AFTER_REQUEST]]..
87 * [[state]]應用程序狀態:應用觸發[[EVENT_AFTER_REQUEST]]
88 */
89 const STATE_AFTER_REQUEST = 4;
90 /**
91 * Application state used by [[state]]: application is about to send response.
92 * [[state]]應用程序狀態:應用程序即將發送響應。
93 */
94 const STATE_SENDING_RESPONSE = 5;
95 /**
96 * Application state used by [[state]]: application has ended.
97 * [[state]]應用程序狀態:應用程序結束。
98 */
99 const STATE_END = 6;
100
101 /**
102 * @var string the namespace that controller classes are located in.控制器類的命名空間位置。
103 * This namespace will be used to load controller classes by prepending it to the controller class name.
104 * The default namespace is `app\controllers`.
105 * 此命名空間將用於負載控制器類重寫它的控制器類的名字。 默認命名空間是`app\controllers`。
106 * Please refer to the [guide about class autoloading](guide:concept-autoloading.md) for more details.
107 */
108 public $controllerNamespace = 'app\\controllers';
109 /**
110 * @var string the application name.應用程序名稱。
111 */
112 public $name = 'My Application';
113 /**
114 * @var string the version of this application.此應用程序的版本。
115 */
116 public $version = '1.0';
117 /**
118 * @var string the charset currently used for the application.目前使用的字符集。
119 */
120 public $charset = 'UTF-8';
121 /**
122 * @var string the language that is meant to be used for end users. It is recommended that you
123 * use [IETF language tags](http://en.wikipedia.org/wiki/IETF_language_tag). For example, `en` stands
124 * for English, while `en-US` stands for English (United States).
125 * 用來作為終端用戶使用的語言
126 * @see sourceLanguage
127 */
128 public $language = 'en-US';
129 /**
130 * @var string the language that the application is written in. This mainly refers to
131 * the language that the messages and view files are written in.
132 * 應用程序編寫的語言。
133 * @see language
134 */
135 public $sourceLanguage = 'en-US';
136 /**
137 * @var Controller the currently active controller instance當前活動控制器實例
138 */
139 public $controller;
140 /**
141 * @var string|boolean the layout that should be applied for views in this application. Defaults to 'main'.
142 * If this is false, layout will be disabled.
143 * 該應用程序中應用的布局。
144 */
145 public $layout = 'main';
146 /**
147 * @var string the requested route請求的路徑 請求的路徑
148 */
149 public $requestedRoute;
150 /**
151 * @var Action the requested Action. If null, it means the request cannot be resolved into an action.
152 * 操作所要求的行動
153 */
154 public $requestedAction;
155 /**
156 * @var array the parameters supplied to the requested action.
157 * 所請求的動作提供的參數。
158 */
159 public $requestedParams;
160 /**
161 * @var array list of installed Yii extensions. Each array element represents a single extension
162 * with the following structure:
163 * 安裝Yii擴展名列表。每個數組元素代表一個擴展
164 *
165 * ~~~
166 * [
167 * 'name' => 'extension name',
168 * 'version' => 'version number',
169 * 'bootstrap' => 'BootstrapClassName', // optional, may also be a configuration array
170 * 'alias' => [
171 * '@alias1' => 'to/path1',
172 * '@alias2' => 'to/path2',
173 * ],
174 * ]
175 * ~~~
176 *
177 * The "bootstrap" class listed above will be instantiated during the application
178 * [[bootstrap()|bootstrapping process]]. If the class implements [[BootstrapInterface]],
179 * its [[BootstrapInterface::bootstrap()|bootstrap()]] method will be also be called.
180 *
181 * If not set explicitly in the application config, this property will be populated with the contents of
182 * 如果在應用程序配置中沒有設置,該屬性將填充到內容
183 * @vendor/yiisoft/extensions.php`.
184 */
185 public $extensions;
186 /**
187 * @var array list of components that should be run during the application [[bootstrap()|bootstrapping process]].
188 * 組件的列表,運行在 [[bootstrap()|bootstrapping process]]中的應用
189 * Each component may be specified in one of the following formats:
190 *
191 * - an application component ID as specified via [[components]].
192 * - a module ID as specified via [[modules]].
193 * - a class name.
194 * - a configuration array.
195 *
196 * During the bootstrapping process, each component will be instantiated. If the component class
197 * implements [[BootstrapInterface]], its [[BootstrapInterface::bootstrap()|bootstrap()]] method
198 * will be also be called.
199 * 在整個啟動過程中,每個組件被實例化。如果組件類提到 [[BootstrapInterface]],
200 * [[BootstrapInterface::bootstrap()|bootstrap()]]方法也會調用
201 */
202 public $bootstrap = [];
203 /**
204 * @var integer the current application state during a request handling life cycle.
205 * This property is managed by the application. Do not modify this property.
206 * 在請求處理生命周期中的當前應用程序狀態。屬性由應用程序管理。不要修改此屬性。
207 */
208 public $state;
209 /**
210 * @var array list of loaded modules indexed by their class names.
211 * 加載模塊列表由它們的類名稱索引組成。
212 */
213 public $loadedModules = [];
214
215
216 /**
217 * Constructor.構造函數
218 * @param array $config name-value pairs that will be used to initialize the object properties.
219 * Note that the configuration must contain both [[id]] and [[basePath]].
220 * 用來初始化對象屬性的 name-value 注意配置必須包含[[id]] 和[[basePath]].
221 * @throws InvalidConfigException if either [[id]] or [[basePath]] configuration is missing.
222 * 如果是修改[[id]] 或[[basePath]] 則配置丟失。
223 */
224 public function __construct($config = [])
225 {
226 Yii::$app = $this;// 將自身的實例綁到Yii的$app上
227 $this->setInstance($this);// 將自身加入到loadedModules中
228
229 $this->state = self::STATE_BEGIN;// 設置狀態為剛開始
230
231 // 做預處理配置
232 $this->preInit($config);
233
234 $this->registerErrorHandler($config);
235
236 Component::__construct($config);
237 }
238
239 /**
240 * Pre-initializes the application. 初始化應用。
241 * This method is called at the beginning of the application constructor.
242 * It initializes several important application properties.
243 * 在構造函數中調用該方法,用於初始化一些重要的屬性
244 * If you override this method, please make sure you call the parent implementation.
245 * @param array $config the application configuration 應用的配置
246 * @throws InvalidConfigException if either [[id]] or [[basePath]] configuration is missing.
247 */
248 public function preInit(&$config)
249 {
250 // 使用了&符號,表示$config的修改會保留
251 if (!isset($config['id'])) {//判斷配置中是否有application ID ,如果沒有,拋出異常
252 throw new InvalidConfigException('The "id" configuration for the Application is required.');
253 }
254 if (isset($config['basePath'])) {
255 // 是否配置項目的root路徑
256 $this->setBasePath($config['basePath']);
257 //賦值給模塊的_basepath屬性,並在設置後刪除
258 unset($config['basePath']);
259 } else {//否則拋出異常
260 throw new InvalidConfigException('The "basePath" configuration for the Application is required.');
261 }
262 //如果配置文件中設置了 vendorPath 使用配置的值,並在設置後刪除,否則使用默認的
263 if (isset($config['vendorPath'])) {
264 $this->setVendorPath($config['vendorPath']);
265 unset($config['vendorPath']);
266 } else {
267 // set "@vendor"
268 $this->getVendorPath();
269 }
270 //如果配置文件中設置了 runtimePath 使用配置的值,並在設置後刪除,否則使用默認的
271 if (isset($config['runtimePath'])) {
272 $this->setRuntimePath($config['runtimePath']);
273 unset($config['runtimePath']);
274 } else {
275 // set "@runtime"
276 $this->getRuntimePath();
277 }
278 //如果配置文件中設置了 timeZone 使用配置的值,並在設置後刪除,否則使用默認的時區
279 if (isset($config['timeZone'])) {
280 $this->setTimeZone($config['timeZone']);
281 unset($config['timeZone']);
282 } elseif (!ini_get('date.timezone')) {
283 $this->setTimeZone('UTC');
284 }
285
286 // merge core components with custom components
287 foreach ($this->coreComponents() as $id => $component) {
288 if (!isset($config['components'][$id])) {
289 // 如果配置中沒有配置相應的核心component,就賦給它
290 $config['components'][$id] = $component;
291 } elseif (is_array($config['components'][$id]) && !isset($config['components'][$id]['class'])) {
292 // 如果存在相應的核心component,但沒有定義它的class,就直接賦到class的key上
293 $config['components'][$id]['class'] = $component['class'];
294 }
295 }
296 }
297
298 /**
299 * @inheritdoc
300 */
301 public function init()
302 {
303 $this->state = self::STATE_INIT;
304 $this->bootstrap();
305 }
306
307 /**
308 * Initializes extensions and executes bootstrap components.初始化擴展並執行初始化程序組件
309 * This method is called by [[init()]] after the application has been fully configured.
310 * 該方法在應用完全配置後被[[init()]]調用
311 * If you override this method, make sure you also call the parent implementation.
312 */
313 protected function bootstrap()
314 {
315 if ($this->extensions === null) {//如果沒有配置,則調用Yii的默認擴展組件
316 $file = Yii::getAlias('@vendor/yiisoft/extensions.php');
317 $this->extensions = is_file($file) ? include($file) : [];
318 }
319 foreach ($this->extensions as $extension) {
320 if (!empty($extension['alias'])) {//如果擴展組件有設置別名
321 foreach ($extension['alias'] as $name => $path) {
322 Yii::setAlias($name, $path);//將給擴展的別名注冊到別名數組中
323 }
324 }
325 if (isset($extension['bootstrap'])) {//如果擴展組件有[[bootstrap]]配置 則初始化給擴展組件
326 $component = Yii::createObject($extension['bootstrap']);
327 if ($component instanceof BootstrapInterface) {
328 Yii::trace("Bootstrap with " . get_class($component) . '::bootstrap()', __METHOD__);
329 $component->bootstrap($this);
330 } else {
331 Yii::trace("Bootstrap with " . get_class($component), __METHOD__);
332 }
333 }
334 }
335
336 foreach ($this->bootstrap as $class) {
337 $component = null;
338 if (is_string($class)) {
339 if ($this->has($class)) {
340 $component = $this->get($class);
341 } elseif ($this->hasModule($class)) {
342 $component = $this->getModule($class);
343 } elseif (strpos($class, '\\') === false) {
344 throw new InvalidConfigException("Unknown bootstrapping component ID: $class");
345 }
346 }
347 if (!isset($component)) {//如果不存在,則調用Yii創建對象
348 $component = Yii::createObject($class);
349 }
350
351 if ($component instanceof BootstrapInterface) {
352 Yii::trace("Bootstrap with " . get_class($component) . '::bootstrap()', __METHOD__);
353 $component->bootstrap($this);
354 } else {
355 Yii::trace("Bootstrap with " . get_class($component), __METHOD__);
356 }
357 }
358 }
未完待續。