今天我们继续来探索Component.php
/** * Makes sure that the behaviors declared in [[behaviors()]] are attached to this component. *确保在声明的行为[behaviors()]]安装此组件。 */ public function ensureBehaviors() { // 如果$this->_behaviors为空,获取$this->behaviors()中的behaviors,并存储到$this->_behaviors数组中 if ($this->_behaviors === null) { $this->_behaviors = []; foreach ($this->behaviors() as $name => $behavior) { $this->attachBehaviorInternal($name, $behavior); } } } /** * Attaches a behavior to this component. * * 内部使用的为该对象添加behavior的方法 * * @param string|integer $name the name of the behavior. If this is an integer, it means the behavior * is an anonymous one. Otherwise, the behavior is a named one and any existing behavior with the same name * will be detached first. * @param string|array|Behavior $behavior the behavior to be attached * @return Behavior the attached behavior. */ private function attachBehaviorInternal($name, $behavior) { if (!($behavior instanceof Behavior)) { // $behavior不是Behavior对象,就认为是配置,通过它创建一个 $behavior = Yii::createObject($behavior); } if (is_int($name)) { $behavior->attach($this); $this->_behaviors[] = $behavior; } else { if (isset($this->_behaviors[$name])) { // 存在就先解绑掉 $this->_behaviors[$name]->detach(); } $behavior->attach($this); $this->_behaviors[$name] = $behavior; } return $behavior; }
下面我们来看一下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; abstract class Application extends Module { 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. */ 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]]. *应用程序触发[EVENT BEFORE_REQUEST]:由[state]使用应用程序状态。 */ const STATE_BEFORE_REQUEST = 2;
/** * 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]]. * @throws InvalidConfigException if either [[id]] or [[basePath]] configuration is missing. */ public function __construct($config = []) { // 将自身的实例绑到Yii的$app上 Yii::$app = $this; // 将自身加入到loadedModules中 $this->setInstance($this); // 设置状态为刚开始 $this->state = self::STATE_BEGIN; // 做预处理,包括设置alias和merge核心components的配置 $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‘])) { throw new InvalidConfigException(‘The "id" configuration for the Application is required.‘); } if (isset($config[‘basePath‘])) { // 项目的root路径 $this->setBasePath($config[‘basePath‘]); // 用完删掉 unset($config[‘basePath‘]); } else { throw new InvalidConfigException(‘The "basePath" configuration for the Application is required.‘); } if (isset($config[‘vendorPath‘])) { $this->setVendorPath($config[‘vendorPath‘]); unset($config[‘vendorPath‘]); } else { // 不存在,就设置默认值 // set "@vendor" $this->getVendorPath(); } if (isset($config[‘runtimePath‘])) { $this->setRuntimePath($config[‘runtimePath‘]); unset($config[‘runtimePath‘]); } else { // 不存在,就设置默认值 // set "@runtime" $this->getRuntimePath(); } 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(); }
/** * Registers the errorHandler component as a PHP error handler. *注册的errorHandler组件作为PHP错误处理程序。 * @param array $config application config */ protected function registerErrorHandler(&$config) { // YII_ENABLE_ERROR_HANDLER,在BaseYii中被定义为true if (YII_ENABLE_ERROR_HANDLER) { if (!isset($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‘]); // 删除掉errorHandler的配置内容 unset($config[‘components‘][‘errorHandler‘]); $this->getErrorHandler()->register(); } } /** * Returns the directory that stores runtime files. * 返回存储运行时文件的目录。 * @return string the directory that stores runtime files. * Defaults to the "runtime" subdirectory under [[basePath]]. */ public function getRuntimePath() { if ($this->_runtimePath === null) { // 不存在,就将其设置为basePath/runtime $this->setRuntimePath($this->getBasePath() . DIRECTORY_SEPARATOR . ‘runtime‘); } return $this->_runtimePath; }
时间: 2024-12-09 22:34:13