Application是所有应用程序类的基类
yii2\base\Application.php。
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\base;
use Yii;
/**
* Application is the base class for all application classes.
* 是所有应用程序类的基类
* @property \yii\web\AssetManager $assetManager The asset manager application component. This property is
* read-only.资产管理器应用组件,只读
* @property \yii\rbac\ManagerInterface $authManager The auth manager application component. Null is returned
* if auth manager is not configured. This property is read-only.认证管理器应用程序组件。未配置返回null,只读
* @property string $basePath The root directory of the application. 应用程序的根目录。
* @property \yii\caching\Cache $cache The cache application component. Null if the component is not enabled.
* This property is read-only.缓存应用程序组件。
* @property \yii\db\Connection $db The database connection. This property is read-only.数据库连接。
* @property \yii\web\ErrorHandler|\yii\console\ErrorHandler $errorHandler The error handler application
* component. This property is read-only.错误处理程序应用程序组件
* @property \yii\i18n\Formatter $formatter The formatter application component. This property is read-only.
* 格式化程序的应用程序组件。
* @property \yii\i18n\I18N $i18n The internationalization application component. This property is read-only.
* 国际化应用组件。
* @property \yii\log\Dispatcher $log The log dispatcher application component. This property is read-only.
* 日志调度程序组件。
* @property \yii\mail\MailerInterface $mailer The mailer application component. This property is read-only.
* 邮件应用程序组件。
* @property \yii\web\Request|\yii\console\Request $request The request component. This property is read-only.
* 请求组件。
* @property \yii\web\Response|\yii\console\Response $response The response component. This property is
* read-only.反应元件。
* @property string $runtimePath The directory that stores runtime files. Defaults to the "runtime"
* subdirectory under [[basePath]].存储运行时文件的目录。
* @property \yii\base\Security $security The security application component. This property is read-only.
* 安全应用组件。
* @property string $timeZone The time zone used by this application.该应用程序使用的时区。
* @property string $uniqueId The unique ID of the module. This property is read-only.模块的唯一标识。
* @property \yii\web\UrlManager $urlManager The URL manager for this application. This property is read-only.
* 此应用程序的网址管理器。
* @property string $vendorPath The directory that stores vendor files. Defaults to "vendor" directory under
* [[basePath]].存储供应商文件的目录。
* @property View|\yii\web\View $view The view application component that is used to render various view
* files. This property is read-only.用于呈现各种视图文件的视图应用程序组件
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
abstract class Application extends Module
{
/**
* @event Event an event raised before the application starts to handle a request.
* 在应用程序开始处理请求之前提出的事件。
*/
const EVENT_BEFORE_REQUEST = 'beforeRequest';
/**
* @event Event an event raised after the application successfully handles a request (before the response is sent out).
* 该应用程序成功处理请求后提出的事件
*/
const EVENT_AFTER_REQUEST = 'afterRequest';
/**
* Application state used by [[state]]: application just started.
* [[state]]适用状态:刚开始应用
*/
const STATE_BEGIN = 0;
/**
* Application state used by [[state]]: application is initializing.
* [[state]]应用程序状态:应用程序初始化。
*/
const STATE_INIT = 1;
/**
* Application state used by [[state]]: application is triggering [[EVENT_BEFORE_REQUEST]].
* [[state]]应用程序状态:应用触发[[EVENT_BEFORE_REQUEST]]
*/
const STATE_BEFORE_REQUEST = 2;
/**
* Application state used by [[state]]: application is handling the request.
* [[state]]应用程序状态:应用程序处理请求。
*/
const STATE_HANDLING_REQUEST = 3;
/**
* Application state used by [[state]]: application is triggering [[EVENT_AFTER_REQUEST]]..
* [[state]]应用程序状态:应用触发[[EVENT_AFTER_REQUEST]]
*/
const STATE_AFTER_REQUEST = 4;
/**
* Application state used by [[state]]: application is about to send response.
* [[state]]应用程序状态:应用程序即将发送响应。
*/
const STATE_SENDING_RESPONSE = 5;
/**
* Application state used by [[state]]: application has ended.
* [[state]]应用程序状态:应用程序结束。
*/
const STATE_END = 6;
/**
* @var string the namespace that controller classes are located in.控制器类的命名空间位置。
* This namespace will be used to load controller classes by prepending it to the controller class name.
* The default namespace is `app\controllers`.
* 此命名空间将用于负载控制器类重写它的控制器类的名字。 默认命名空间是`app\controllers`。
* Please refer to the [guide about class autoloading](guide:concept-autoloading.md) for more details.
*/
public $controllerNamespace = 'app\\controllers';
/**
* @var string the application name.应用程序名称。
*/
public $name = 'My Application';
/**
* @var string the version of this application.此应用程序的版本。
*/
public $version = '1.0';
/**
* @var string the charset currently used for the application.目前使用的字符集。
*/
public $charset = 'UTF-8';
/**
* @var string the language that is meant to be used for end users. It is recommended that you
* use [IETF language tags](http://en.wikipedia.org/wiki/IETF_language_tag). For example, `en` stands
* for English, while `en-US` stands for English (United States).
* 用来作为终端用户使用的语言
* @see sourceLanguage
*/
public $language = 'en-US';
/**
* @var string the language that the application is written in. This mainly refers to
* the language that the messages and view files are written in.
* 应用程序编写的语言。
* @see language
*/
public $sourceLanguage = 'en-US';
/**
* @var Controller the currently active controller instance当前活动控制器实例
*/
public $controller;
/**
* @var string|boolean the layout that should be applied for views in this application. Defaults to 'main'.
* If this is false, layout will be disabled.
* 该应用程序中应用的布局。
*/
public $layout = 'main';
/**
* @var string the requested route请求的路径 请求的路径
*/
public $requestedRoute;
/**
* @var Action the requested Action. If null, it means the request cannot be resolved into an action.
* 操作所要求的行动
*/
public $requestedAction;
/**
* @var array the parameters supplied to the requested action.
* 所请求的动作提供的参数。
*/
public $requestedParams;
/**
* @var array list of installed Yii extensions. Each array element represents a single extension
* with the following structure:
* 安装Yii扩展名列表。每个数组元素代表一个扩展
*
* ~~~
* [
* 'name' => 'extension name',
* 'version' => 'version number',
* 'bootstrap' => 'BootstrapClassName', // optional, may also be a configuration array
* 'alias' => [
* '@alias1' => 'to/path1',
* '@alias2' => 'to/path2',
* ],
* ]
* ~~~
*
* The "bootstrap" class listed above will be instantiated during the application
* [[bootstrap()|bootstrapping process]]. If the class implements [[BootstrapInterface]],
* its [[BootstrapInterface::bootstrap()|bootstrap()]] method will be also be called.
*
* If not set explicitly in the application config, this property will be populated with the contents of
* 如果在应用程序配置中没有设置,该属性将填充到内容
* @vendor/yiisoft/extensions.php`.
*/
public $extensions;
/**
* @var array list of components that should be run during the application [[bootstrap()|bootstrapping process]].
* 组件的列表,运行在 [[bootstrap()|bootstrapping process]]中的应用
* Each component may be specified in one of the following formats:
*
* - an application component ID as specified via [[components]].
* - a module ID as specified via [[modules]].
* - a class name.
* - a configuration array.
*
* During the bootstrapping process, each component will be instantiated. If the component class
* implements [[BootstrapInterface]], its [[BootstrapInterface::bootstrap()|bootstrap()]] method
* will be also be called.
* 在整个启动过程中,每个组件被实例化。如果组件类提到 [[BootstrapInterface]],
* [[BootstrapInterface::bootstrap()|bootstrap()]]方法也会调用
*/
public $bootstrap = [];
/**
* @var integer the current application state during a request handling life cycle.
* This property is managed by the application. Do not modify this property.
* 在请求处理生命周期中的当前应用程序状态。属性由应用程序管理。不要修改此属性。
*/
public $state;
/**
* @var array list of loaded modules indexed by their class names.
* 加载模块列表由它们的类名称索引组成。
*/
public $loadedModules = [];
/**
* Constructor.构造函数
* @param array $config name-value pairs that will be used to initialize the object properties.
* Note that the configuration must contain both [[id]] and [[basePath]].
* 用来初始化对象属性的 name-value 注意配置必须包含[[id]] 和[[basePath]].
* @throws InvalidConfigException if either [[id]] or [[basePath]] configuration is missing.
* 如果是修改[[id]] 或[[basePath]] 则配置丢失。
*/
public function __construct($config = [])
{
Yii::$app = $this;// 将自身的实例绑到Yii的$app上
$this->setInstance($this);// 将自身加入到loadedModules中
$this->state = self::STATE_BEGIN;// 设置状态为刚开始
// 做预处理配置
$this->preInit($config);
$this->registerErrorHandler($config);
Component::__construct($config);
}
/**
* Pre-initializes the application. 初始化应用。
* This method is called at the beginning of the application constructor.
* It initializes several important application properties.
* 在构造函数中调用该方法,用于初始化一些重要的属性
* If you override this method, please make sure you call the parent implementation.
* @param array $config the application configuration 应用的配置
* @throws InvalidConfigException if either [[id]] or [[basePath]] configuration is missing.
*/
public function preInit(&$config)
{
// 使用了&符号,表示$config的修改会保留
if (!isset($config['id'])) {//判断配置中是否有application ID ,如果没有,抛出异常
throw new InvalidConfigException('The "id" configuration for the Application is required.');
}
if (isset($config['basePath'])) {
// 是否配置项目的root路径
$this->setBasePath($config['basePath']);
//赋值给模块的_basepath属性,并在设置后删除
unset($config['basePath']);
} else {//否则抛出异常
throw new InvalidConfigException('The "basePath" configuration for the Application is required.');
}
//如果配置文件中设置了 vendorPath 使用配置的值,并在设置后删除,否则使用默认的
if (isset($config['vendorPath'])) {
$this->setVendorPath($config['vendorPath']);
unset($config['vendorPath']);
} else {
// set "@vendor"
$this->getVendorPath();
}
//如果配置文件中设置了 runtimePath 使用配置的值,并在设置后删除,否则使用默认的
if (isset($config['runtimePath'])) {
$this->setRuntimePath($config['runtimePath']);
unset($config['runtimePath']);
} else {
// set "@runtime"
$this->getRuntimePath();
}
//如果配置文件中设置了 timeZone 使用配置的值,并在设置后删除,否则使用默认的时区
if (isset($config['timeZone'])) {
$this->setTimeZone($config['timeZone']);
unset($config['timeZone']);
} elseif (!ini_get('date.timezone')) {
$this->setTimeZone('UTC');
}
// merge core components with custom components
foreach ($this->coreComponents() as $id => $component) {
if (!isset($config['components'][$id])) {
// 如果配置中没有配置相应的核心component,就赋给它
$config['components'][$id] = $component;
} elseif (is_array($config['components'][$id]) && !isset($config['components'][$id]['class'])) {
// 如果存在相应的核心component,但没有定义它的class,就直接赋到class的key上
$config['components'][$id]['class'] = $component['class'];
}
}
}
/**
* @inheritdoc
*/
public function init()
{
$this->state = self::STATE_INIT;
$this->bootstrap();
}
/**
* Initializes extensions and executes bootstrap components.初始化扩展并执行初始化程序组件
* This method is called by [[init()]] after the application has been fully configured.
* 该方法在应用完全配置后被[[init()]]调用
* If you override this method, make sure you also call the parent implementation.
*/
protected function bootstrap()
{
if ($this->extensions === null) {//如果没有配置,则调用Yii的默认扩展组件
$file = Yii::getAlias('@vendor/yiisoft/extensions.php');
$this->extensions = is_file($file) ? include($file) : [];
}
foreach ($this->extensions as $extension) {
if (!empty($extension['alias'])) {//如果扩展组件有设置别名
foreach ($extension['alias'] as $name => $path) {
Yii::setAlias($name, $path);//将给扩展的别名注册到别名数组中
}
}
if (isset($extension['bootstrap'])) {//如果扩展组件有[[bootstrap]]配置 则初始化给扩展组件
$component = Yii::createObject($extension['bootstrap']);
if ($component instanceof BootstrapInterface) {
Yii::trace("Bootstrap with " . get_class($component) . '::bootstrap()', __METHOD__);
$component->bootstrap($this);
} else {
Yii::trace("Bootstrap with " . get_class($component), __METHOD__);
}
}
}
foreach ($this->bootstrap as $class) {
$component = null;
if (is_string($class)) {
if ($this->has($class)) {
$component = $this->get($class);
} elseif ($this->hasModule($class)) {
$component = $this->getModule($class);
} elseif (strpos($class, '\\') === false) {
throw new InvalidConfigException("Unknown bootstrapping component ID: $class");
}
}
if (!isset($component)) {//如果不存在,则调用Yii创建对象
$component = Yii::createObject($class);
}
if ($component instanceof BootstrapInterface) {
Yii::trace("Bootstrap with " . get_class($component) . '::bootstrap()', __METHOD__);
$component->bootstrap($this);
} else {
Yii::trace("Bootstrap with " . get_class($component), __METHOD__);
}
}
}
/**
* Registers the errorHandler component as a PHP error handler.
* 注册errorHandler组件作为PHP错误处理函数
* @param array $config application config 应用程序配置
*/
protected function registerErrorHandler(&$config)
{
if (YII_ENABLE_ERROR_HANDLER) {// YII_ENABLE_ERROR_HANDLER在BaseYii中被定义为true
if (!isset($config['components']['errorHandler']['class'])) {
//$config['components']['errorHandler']['class']不存在结束运行
echo "Error: no errorHandler component is configured.\n";
exit(1);
}
//将$config['components']['errorHandler']的内容设置到了$this->_definitions['errorHandler']中
$this->set('errorHandler', $config['components']['errorHandler']);
unset($config['components']['errorHandler']);// 删除掉配置内容
$this->getErrorHandler()->register();
}
}
/**
* Returns an ID that uniquely identifies this module among all modules within the current application.
* Since this is an application instance, it will always return an empty string.
* 返回在当前应用程序中该模块的唯一标识。这是一个应用实例,它将返回一个空字符串。
* @return string the unique ID of the module.模块的唯一标识。
*/
public function getUniqueId()
{
return '';
}
/**
* Sets the root directory of the application and the @app alias.设置应用程序的根目录 @ 加应用程序别名。
* This method can only be invoked at the beginning of the constructor.只能在构造函数开始时调用该方法
* @param string $path the root directory of the application.应用程序的根目录。
* @property string the root directory of the application. 应用程序的根目录。
* @throws InvalidParamException if the directory does not exist. 如果目录不存在。抛出异常
*/
public function setBasePath($path)
{
parent::setBasePath($path);
// 使用@app来记录basePath
Yii::setAlias('@app', $this->getBasePath());
}
/**
* Runs the application. 运行应用程序。
* This is the main entrance of an application. 应用程序的主要入口。
* @return integer the exit status (0 means normal, non-zero values mean abnormal) 状态(0正常,非0为不正常)
*/
public function run()
{
try {
$this->state = self::STATE_BEFORE_REQUEST;
$this->trigger(self::EVENT_BEFORE_REQUEST);//加载事件函数beforRequest函数
$this->state = self::STATE_HANDLING_REQUEST;
$response = $this->handleRequest($this->getRequest());//加载控制器 获取Request对象
$this->state = self::STATE_AFTER_REQUEST;
$this->trigger(self::EVENT_AFTER_REQUEST);//加载afterRequest事件函数
$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;
}
}
/**
* Handles the specified request.
* 处理指定的请求
* This method should return an instance of [[Response]] or its child class
* which represents the handling result of the request.
* 该方法应该返回一个[[Response]]实例,或者它的子类代表处理请求的结果
* @param Request $request the request to be handled 被处理的请求
* @return Response the resulting response 得到的响应
*/
abstract public function handleRequest($request);
private $_runtimePath;
/**
* Returns the directory that stores runtime files.返回存储运行时文件的路径
* @return string the directory that stores runtime files.存储运行时文件的目录。
* Defaults to the "runtime" subdirectory under [[basePath]].默认返回[[basePath]]下的 "runtime"目录
*/
public function getRuntimePath()
{
if ($this->_runtimePath === null) {//设置临时文件存储路径
$this->setRuntimePath($this->getBasePath() . DIRECTORY_SEPARATOR . 'runtime');
}
return $this->_runtimePath;
}
/**
* Sets the directory that stores runtime files.设置存储运行时文件的路径
* @param string $path the directory that stores runtime files.存储运行时文件的目录。
*/
public function setRuntimePath($path)
{
// 获取runtimePath的路径,并存到_runtimePath中
$this->_runtimePath = Yii::getAlias($path);
// 使用@runtime来记录 runtimePath
Yii::setAlias('@runtime', $this->_runtimePath);
}
private $_vendorPath;
/**
* Returns the directory that stores vendor files.返回插件文件的目录。
* @return string the directory that stores vendor files.
* Defaults to "vendor" directory under [[basePath]].
* 默认返回[[basePath]]下的 "vendor" 目录
*/
public function getVendorPath()
{
if ($this->_vendorPath === null) {
// 不存在,就将其设置为basePath/vendor
$this->setVendorPath($this->getBasePath() . DIRECTORY_SEPARATOR . 'vendor');
}
return $this->_vendorPath;
}
/**
* Sets the directory that stores vendor files.设置插件目录路径,并设置别名
* @param string $path the directory that stores vendor files.
*/
public function setVendorPath($path)
{
$this->_vendorPath = Yii::getAlias($path);// 获取vendor的路径,并存到_vendorPath中
Yii::setAlias('@vendor', $this->_vendorPath);// 设置@vendor的alias
Yii::setAlias('@bower', $this->_vendorPath . DIRECTORY_SEPARATOR . 'bower');
Yii::setAlias('@npm', $this->_vendorPath . DIRECTORY_SEPARATOR . 'npm');
}
/**
* Returns the time zone used by this application.取得时区
* This is a simple wrapper of PHP function date_default_timezone_get().
* If time zone is not configured in php.ini or application config,
* it will be set to UTC by default.
* @return string the time zone used by this application.
* @see http://php.net/manual/en/function.date-default-timezone-get.php
*/
public function getTimeZone()
{
return date_default_timezone_get();
}
/**
* Sets the time zone used by this application.设置时区
* This is a simple wrapper of PHP function date_default_timezone_set().
* Refer to the [php manual](http://www.php.net/manual/en/timezones.php) for available timezones.
* @param string $value the time zone used by this application.
* @see http://php.net/manual/en/function.date-default-timezone-set.php
*/
public function setTimeZone($value)
{
date_default_timezone_set($value);
}
/**
* Returns the database connection component.返回数据库连接组件
* @return \yii\db\Connection the database connection.
*/
public function getDb()
{
return $this->get('db');
}
/**
* Returns the log dispatcher component.返回日志调度组件
* @return \yii\log\Dispatcher the log dispatcher application component.
*/
public function getLog()
{
return $this->get('log');
}
/**
* Returns the error handler component.返回错误处理组件
* @return \yii\web\ErrorHandler|\yii\console\ErrorHandler the error handler application component.
*/
public function getErrorHandler()
{
return $this->get('errorHandler');
}
/**
* Returns the cache component.返回缓存组件
* @return \yii\caching\Cache the cache application component. Null if the component is not enabled.
*/
public function getCache()
{
return $this->get('cache', false);
}
/**
* Returns the formatter component.返回格式化程序组件
* @return \yii\i18n\Formatter the formatter application component.
*/
public function getFormatter()
{
return $this->get('formatter');
}
/**
* Returns the request component.返回请求的组件对象
* @return \yii\web\Request|\yii\console\Request the request component.
*/
public function getRequest()
{
return $this->get('request');
}
/**
* Returns the response component.返回响应组件
* @return \yii\web\Response|\yii\console\Response the response component.
*/
public function getResponse()
{
return $this->get('response');
}
/**
* Returns the view object.返回视图对象
* @return View|\yii\web\View the view application component that is used to render various view files.
*/
public function getView()
{
return $this->get('view');
}
/**
* Returns the URL manager for this application.返回当前应用的URL管理组件
* @return \yii\web\UrlManager the URL manager for this application.
*/
public function getUrlManager()
{
return $this->get('urlManager');
}
/**
* Returns the internationalization (i18n) component返回国际化组件
* @return \yii\i18n\I18N the internationalization application component.
*/
public function getI18n()
{
return $this->get('i18n');
}
/**
* Returns the mailer component.返回邮件组件
* @return \yii\mail\MailerInterface the mailer application component.
*/
public function getMailer()
{
return $this->get('mailer');
}
/**
* Returns the auth manager for this application.返回该应用的权限管理组件
* @return \yii\rbac\ManagerInterface the auth manager application component.
* Null is returned if auth manager is not configured. 管理权限没有配置返回null
*/
public function getAuthManager()
{
return $this->get('authManager', false);
}
/**
* Returns the asset manager.返回资源管理组件
* @return \yii\web\AssetManager the asset manager application component.
*/
public function getAssetManager()
{
return $this->get('assetManager');
}
/**
* Returns the security component.返回安全组件
* @return \yii\base\Security the security application component.
*/
public function getSecurity()
{
return $this->get('security');
}
/**
* Returns the configuration of core application components.返回核心组件的配置
* @see set()
*/
public function coreComponents()
{
return [
'log' => ['class' => 'yii\log\Dispatcher'],
'view' => ['class' => 'yii\web\View'],
'formatter' => ['class' => 'yii\i18n\Formatter'],
'i18n' => ['class' => 'yii\i18n\I18N'],
'mailer' => ['class' => 'yii\swiftmailer\Mailer'],
'urlManager' => ['class' => 'yii\web\UrlManager'],
'assetManager' => ['class' => 'yii\web\AssetManager'],
'security' => ['class' => 'yii\base\Security'],
];
}
/**
* Terminates the application.终止应用程序
* This method replaces the `exit()` function by ensuring the application life cycle is completed
* before terminating the application.该方法代替`exit()` 确认一个应用的生命周期已经结束
* @param integer $status the exit status (value 0 means normal exit while other values mean abnormal exit).
* @param Response $response the response to be sent. If not set, the default application [[response]] component will be used.
* @throws ExitException if the application is in testing mode
*/
public function end($status = 0, $response = null)
{
if ($this->state === self::STATE_BEFORE_REQUEST || $this->state === self::STATE_HANDLING_REQUEST) {
//判断当前状态为请求前或者处理请求
$this->state = self::STATE_AFTER_REQUEST;//设置应用状态为请求完成后
$this->trigger(self::EVENT_AFTER_REQUEST);
}
if ($this->state !== self::STATE_SENDING_RESPONSE && $this->state !== self::STATE_END) {
//如果应用状态不是发送应答和应用结束
$this->state = self::STATE_END;//设置状态为应用结束
$response = $response ? : $this->getResponse();
$response->send();//向客户端发送应答
}
if (YII_ENV_TEST) {
throw new ExitException($status);
} else {
exit($status);
}
}