今天本來打算研究一下yii2.0的AR模型的實現(xiàn)原理,然而,計劃趕不上變化,突然就想先研究一下yii2.0的數(shù)據(jù)庫組件創(chuàng)建的過程。通過對yii源碼的學習,了解了yii組件注冊與創(chuàng)建的過程,并發(fā)現(xiàn)原來yii組件注冊之后并不是馬上就去創(chuàng)建的,而是待到實際需要使用某個組件的時候再去創(chuàng)建對應的組件實例的。本文大概記錄一下這個探索的過程。
要了解yii組件的注冊與創(chuàng)建,當然要從yii入口文件index.php說起了,整個文件代碼如下:
<?php defined('YII_DEBUG') or define('YII_DEBUG', true); defined('YII_ENV') or define('YII_ENV', 'dev'); require(__DIR__ . '/../../vendor/autoload.php'); require(__DIR__ . '/../../vendor/yiisoft/yii2/Yii.php'); require(__DIR__ . '/../../common/config/bootstrap.php'); require(__DIR__ . '/../config/bootstrap.php'); $config = yii\helpers\ArrayHelper::merge( require(__DIR__ . '/../../common/config/main.php'), require(__DIR__ . '/../../common/config/main-local.php'), require(__DIR__ . '/../config/main.php'), require(__DIR__ . '/../config/main-local.php') ); (new yii\web\Application($config))->run();
可以看到入口文件引入了幾個配置文件,并將所有配置文件的內容都合并到$config這個配置數(shù)組中,然后使用這個配置數(shù)組作為參數(shù)去創(chuàng)建一個應用實例。若將這個配置數(shù)組打印出來,就會看到,“components”下標對應的元素包含了yii組件的參數(shù)信息(這里只截圖一小部分):
這些組件的信息是在引入進來的幾個配置文件中配置的,Yii組件就是使用這些參數(shù)信息進行注冊與創(chuàng)建的。
接下來就進入yii\web\Application類的實例化過程了,yii\web\Application類沒有構造函數(shù),但是它繼承了\yii\base\Application類:
所以會自動執(zhí)行\(zhòng)yii\base\Application類的構造函數(shù):
public function __construct($config = []) { Yii::$app = $this; static::setInstance($this); $this->state = self::STATE_BEGIN; $this->preInit($config); $this->registerErrorHandler($config); Component::__construct($config); }
這里要順便說一下預初始化方法preInit(),它的代碼如下:
public function preInit(&$config) { /* 此處省略對$config數(shù)組的預處理操作代碼 */ // merge core components with custom components 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']; } } }
這個函數(shù)對傳遞給構造函數(shù)的配置數(shù)組$config進行了一些預處理操作(這里省略了),最后使用coreComponents()方法返回的數(shù)組對$config數(shù)組進行了完善,coreComponents()方法是這樣的:
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'], ]; }
其實就是一些核心組件的配置,也就是說這些組件是可以不需要我們在配置文件中配置的,yii會自動進行注冊。
好了,回到\yii\base\Application類的構造函數(shù),這個函數(shù)最后調用了\yii\base\Component類的構造函數(shù),但\yii\base\Component類是沒有構造函數(shù)的,不過它繼承了\yii\base\Object類:
所以也自動執(zhí)行了\yii\base\Object類的構造函數(shù):
public function __construct($config = []) { if (!empty($config)) { Yii::configure($this, $config); } $this->init();
}
這里主要是調用了\yii\BaseYii類的靜態(tài)方法configure():
public static function configure($object, $properties) { foreach ($properties as $name => $value) { $object->$name = $value; } return $object; }