婷婷综合国产,91蜜桃婷婷狠狠久久综合9色 ,九九九九九精品,国产综合av

主頁 > 知識庫 > Yii2中組件的注冊與創建方法

Yii2中組件的注冊與創建方法

熱門標簽:周口網絡回撥外呼系統 福建高頻外呼防封系統哪家好 外呼系統人工客服 全國各省地圖標注點 網絡電話400申請 百度地圖標注類型是酒店 商丘外呼系統好處 400電話申請辦理 隨州銷售電銷機器人公司

 今天本來打算研究一下yii2.0的AR模型的實現原理,然而,計劃趕不上變化,突然就想先研究一下yii2.0的數據庫組件創建的過程。通過對yii源碼的學習,了解了yii組件注冊與創建的過程,并發現原來yii組件注冊之后并不是馬上就去創建的,而是待到實際需要使用某個組件的時候再去創建對應的組件實例的。本文大概記錄一下這個探索的過程。

  要了解yii組件的注冊與創建,當然要從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這個配置數組中,然后使用這個配置數組作為參數去創建一個應用實例。若將這個配置數組打印出來,就會看到,“components”下標對應的元素包含了yii組件的參數信息(這里只截圖一小部分):

這些組件的信息是在引入進來的幾個配置文件中配置的,Yii組件就是使用這些參數信息進行注冊與創建的。

  接下來就進入yii\web\Application類的實例化過程了,yii\web\Application類沒有構造函數,但是它繼承了\yii\base\Application類:

所以會自動執行\yii\base\Application類的構造函數:

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數組的預處理操作代碼 */
 // 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'];
  }
 }
}

  這個函數對傳遞給構造函數的配置數組$config進行了一些預處理操作(這里省略了),最后使用coreComponents()方法返回的數組對$config數組進行了完善,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類的構造函數,這個函數最后調用了\yii\base\Component類的構造函數,但\yii\base\Component類是沒有構造函數的,不過它繼承了\yii\base\Object類:

所以也自動執行了\yii\base\Object類的構造函數:

public function __construct($config = [])
{
 if (!empty($config)) {
  Yii::configure($this, $config);
 }
 $this->init();
}

這里主要是調用了\yii\BaseYii類的靜態方法configure():

public static function configure($object, $properties)
{
 foreach ($properties as $name => $value) {
  $object->$name = $value;
 }
 return $object;
}

這個方法就是循環入口文件(new yii\web\Application($config))->run();中的$config數組(這個數組的結構參見本文第一個截圖),以數組鍵名作為對象屬性名,對應的鍵值作為對象屬性值進行賦值操作。所以當循環到組件配置參數的時候是這樣子的:$object->components = $value($value為所有組件的配置數組),也就是對$object的components屬性進行賦值操作,那這個$object是哪個類的對象呢?回想最初調用的源頭,其實它就是入口文件中需要進行實例化的\yii\web\Application類的對象啊。然而,這個類和它的祖先類都沒有components這個成員變量啊,不急,又要進行一番繼承套路了,順著yii\web\Application類的繼承關系一層一層往上找可以發現\yii\web\Application類最終也繼承了\yii\base\Object類,\yii\base\Object類是支持屬性的,所以yii\web\Application類也支持屬性(關于屬性,可以參考我的另一篇博文:yii2之屬性),當賦值操作找不到components成員變量時會調用setComponents()方法,又去找這個方法的所在,終于在它的祖先類\yii\di\ServiceLocator中找到了setComponents()方法,沒錯,對應用實例的components屬性進行賦值操作其實就是調用這個方法!

  好了,現在就來看看setComponents()這個方法到底干了啥:

public function setComponents($components)
{
 foreach ($components as $id => $component) {
  $this->set($id, $component);
 }
}

其實很簡單,就是循環各個組件的配置數組,調用set()方法,set()方法如下:

public function set($id, $definition)
{ unset($this->_components[$id]);
 if ($definition === null) {
  unset($this->_definitions[$id]);
  return;
 }
 if (is_object($definition) || is_callable($definition, true)) {
  // an object, a class name, or a PHP callable
  $this->_definitions[$id] = $definition;
 } elseif (is_array($definition)) {
  // a configuration array
  if (isset($definition['class'])) {
   $this->_definitions[$id] = $definition;
  } else {
   throw new InvalidConfigException("The configuration for the \"$id\" component must contain a \"class\" element.");
  }
 } else {
  throw new InvalidConfigException("Unexpected configuration type for the \"$id\" component: " . gettype($definition));
 }
}

其實就是把組件配置存入$_definitions這個私有成員變量(即注冊),然后呢?然后就沒有下文了。。。

  搞了半天,原來yii創建應用實例的時候只是進行組件的注冊,并沒有實際創建組件,那么組件實例是什么時候進行創建的?在哪里進行創建的呢?別急。從上面推導的這個過程我們知道\yii\di\ServiceLocator類是\yii\web\Application類的祖先類,所以其實yii的應用實例其實就是一個服務定位器,比如我們想訪問數據庫組件的時候,我們可以這樣來訪問:Yii::$app->db,這個Yii::$app就是yii應用實例,也就是\yii\web\Application類的實例,但是\yii\web\Application類和它的父類、祖先類都找不到db這個屬性啊。哈哈,別忘了,php讀取不到類屬性的時候會調用魔術方法__get(),所以開始查找\yii\web\Application繼承關系最近的祖先類中的__get()方法,最后在\yii\di\ServiceLocator類中找到了,也就是說,Yii::$app->db最終會調用\yii\di\ServiceLocator類中的__get()方法:

public function __get($name)
{
 if ($this->has($name)) {
  return $this->get($name);
 } else {
  return parent::__get($name);
 }
}

__get()方法首先調用has()方法(這個不再貼代碼了)判斷組件是否已注冊,若已注冊則調用get()方法:

public function get($id, $throwException = true)
{
 if (isset($this->_components[$id])) {
  return $this->_components[$id];
 }
 if (isset($this->_definitions[$id])) {
  $definition = $this->_definitions[$id];
  if (is_object($definition)  !$definition instanceof Closure) {
   return $this->_components[$id] = $definition;
  } else {
   return $this->_components[$id] = Yii::createObject($definition);
  }
 } elseif ($throwException) {
  throw new InvalidConfigException("Unknown component ID: $id");
 } else {
  return null;
 }
}

其中私有成員變量$_components是存儲已經創建的組件實例的,若發現組件已經創建過則直接返回組件示例,否則使用$_definitions中對應組件的注冊信息,調用\yii\BaseYii::createObject()方法進行組件創建,這個方法最終會調用依賴注入容器\yii\di\Container的get()方法,接著就是依賴注入創建對象的過程了,關于這個過程已經在我的上一篇博文中講解過了,可以參考一下:yii2之依賴注入與依賴注入容器。

  好了,yii組件注冊與創建的整個過程就是這樣的。最后總結一下,其實yii創建應用實例的時候只是進行了各個組件的注冊,也就是將組件的配置信息存入\yii\di\ServiceLocator類的私有成員變量$_definitions中,并沒有進行實際創建,等到程序運行過程中真正需要使用到某個組件的時候才根據該組件在$_definitions中保存的注冊信息使用依賴注入容器\yii\di\Container進行組件實例的創建,然后把創建的實例存入私有成員變量$_components,這樣下次訪問相同組件的時候就可以直接返回組件實例,而不再需要執行創建過程了。yii的這個組件注冊與創建機制其實是大有裨益的,試想一下,如果在應用實例創建的時候就進行所有組件的創建,將會大大增加應用實例創建的時間,用戶每次刷新頁面都會進行應用實例的創建的,也就是說用戶每刷新一次頁面都很慢,這用戶體驗就很不好了,而且很多情況下有很多組件其實是沒有使用到的,但是我們還是花了不少時間去創建這些組件,這是很不明智的,所以yii的做法就是:先把組件參數信息保存起來,需要使用到哪些組件再去創建相應的實例,大大節省了應用創建的時間,同時也節省了內存,這種思路是很值得我們學習的!

總結

以上所述是小編給大家介紹的Yii2中組件的注冊與創建方法,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對腳本之家網站的支持!

您可能感興趣的文章:
  • Yii框架學習筆記之應用組件操作示例
  • yii2高級應用之自定義組件實現全局使用圖片上傳功能的方法
  • Yii框架組件和事件行為管理詳解
  • Yii擴展組件編寫方法實例分析
  • yii2行為的方法如何注入到組件類中詳解
  • Yii框架響應組件用法實例分析
  • Yii框架核心組件類實例詳解
  • PHP的Yii框架中移除組件所綁定的行為的方法
  • Yii框架自定義數據庫操作組件示例
  • Yii框架組件的事件機制原理與用法分析
  • Yii框架應用組件用法實例分析

標簽:海南 十堰 定西 樂山 佛山 迪慶 南寧 六安

巨人網絡通訊聲明:本文標題《Yii2中組件的注冊與創建方法》,本文關鍵詞  Yii2,中,組件,的,注冊,與,;如發現本文內容存在版權問題,煩請提供相關信息告之我們,我們將及時溝通與處理。本站內容系統采集于網絡,涉及言論、版權與本站無關。
  • 相關文章
  • 下面列出與本文章《Yii2中組件的注冊與創建方法》相關的同類信息!
  • 本頁收集關于Yii2中組件的注冊與創建方法的相關信息資訊供網民參考!
  • 推薦文章
    婷婷综合国产,91蜜桃婷婷狠狠久久综合9色 ,九九九九九精品,国产综合av
    亚洲女同一区二区| 国产99久久久久| 日韩av网站在线观看| 毛片av一区二区| 国产美女一区二区三区| 日韩一级完整毛片| 成人性生交大片免费看中文| 亚洲精品五月天| 欧美精品久久天天躁| 国产日韩亚洲欧美综合| 久久成人免费电影| 欧美老肥妇做.爰bbww视频| 中文字幕一区二区三区不卡| 国产丝袜美腿一区二区三区| 欧美日精品一区视频| 日本在线观看不卡视频| 欧美日韩中文国产| 日韩高清在线一区| 亚洲一区二区三区三| 久久精品这里都是精品| 欧美嫩在线观看| 精品一区二区免费在线观看| 亚洲va欧美va天堂v国产综合| 日韩一级精品视频在线观看| 色婷婷激情综合| av影院午夜一区| 94色蜜桃网一区二区三区| 粉嫩高潮美女一区二区三区| 丝袜脚交一区二区| 亚洲综合丁香婷婷六月香| 欧美变态tickling挠脚心| 日韩一区二区三区观看| 亚洲人成伊人成综合网小说| 久久无码av三级| 欧美变态tickling挠脚心| 91蜜桃网址入口| 欧美在线高清视频| 欧美日韩精品综合在线| 波多野结衣精品在线| 91在线观看视频| 国产福利精品导航| 国产麻豆视频精品| 一区二区在线观看av| 亚洲一二三区在线观看| 一区二区免费视频| 亚洲激情图片小说视频| 激情综合网最新| 色综合久久久久网| 91精品国产综合久久久久| 欧美日韩色综合| 欧美美女一区二区| 国产日韩欧美电影| 依依成人综合视频| 懂色一区二区三区免费观看| 在线观看亚洲精品| 制服丝袜激情欧洲亚洲| 国产精品视频免费| 午夜伊人狠狠久久| 在线观看日韩一区| 精品国精品国产| 婷婷六月综合亚洲| 欧美性三三影院| 亚洲欧美一区二区三区国产精品| 视频一区中文字幕| 91年精品国产| 久久综合999| 一区二区三区产品免费精品久久75| 国产成人精品一区二| 3751色影院一区二区三区| 国产精品少妇自拍| 激情久久五月天| 欧美乱熟臀69xxxxxx| 午夜精品久久久久久久久久 | 欧美极品aⅴ影院| 黄色日韩网站视频| 亚洲视频在线一区| 国产精品拍天天在线| 国产亚洲综合色| 亚洲国产成人一区二区三区| 国产精品天干天干在线综合| 亚洲aⅴ怡春院| 久草在线在线精品观看| 成人激情黄色小说| 欧美一二三在线| 国产精品成人免费在线| 亚洲电影欧美电影有声小说| 蓝色福利精品导航| 92国产精品观看| 欧美v日韩v国产v| 亚洲日韩欧美一区二区在线| 久久精品国产亚洲5555| 最新国产成人在线观看| 成人免费高清在线| 久久色.com| 91黄色小视频| 久久精品国产亚洲aⅴ| 日韩va亚洲va欧美va久久| 国产精品国产精品国产专区不蜜| fc2成人免费人成在线观看播放| 亚洲综合色网站| 日韩一区二区在线免费观看| 国产制服丝袜一区| 国产一区二区在线看| 亚洲成av人**亚洲成av**| 国产精品高潮呻吟| 午夜精品久久久久久久久久久| 在线视频一区二区免费| 一区二区三区欧美日韩| 9l国产精品久久久久麻豆| 亚洲精品伦理在线| 一区二区三区四区激情| 国产精品电影院| 一区精品在线播放| 国产精品国产精品国产专区不蜜| 亚洲免费伊人电影| 午夜精品影院在线观看| 激情欧美一区二区| 福利一区二区在线观看| 这里只有精品99re| 色综合天天性综合| 狠狠色狠狠色综合系列| 国产乱理伦片在线观看夜一区| 国产91在线看| 91搞黄在线观看| 日韩一区二区三区精品视频 | 一本一本大道香蕉久在线精品| 欧美精品一区二区三区高清aⅴ| 亚洲精品美国一| 亚洲欧美在线aaa| 精品一区二区影视| 99综合电影在线视频| 日韩视频在线你懂得| 亚洲婷婷国产精品电影人久久| 免费成人av资源网| 日韩欧美中文字幕精品| 亚洲综合成人网| 欧美久久高跟鞋激| 丝瓜av网站精品一区二区| 欧美高清性hdvideosex| 精品黑人一区二区三区久久| 国产精品午夜久久| 亚洲一区二区三区精品在线| 91老师片黄在线观看| 国产婷婷一区二区| 亚洲成人一区在线| 欧美一区二区大片| 亚洲成人你懂的| 久久只精品国产| 亚洲成a人v欧美综合天堂下载| 亚洲国产综合91精品麻豆| 久久er99精品| 亚洲午夜久久久久| 国产欧美一区二区精品性色| 在线观看视频一区二区| 国产精品综合二区| 日本成人在线看| 视频在线在亚洲| 亚洲精品国产高清久久伦理二区| 日韩精品专区在线影院观看| 欧美久久久久免费| 欧美日韩国产一区二区三区地区| 粉嫩aⅴ一区二区三区四区五区| 激情综合色综合久久综合| 蜜桃视频一区二区三区在线观看| 日韩一区二区三区四区| 国产精品国产三级国产| 91成人免费在线视频| 国产aⅴ综合色| 亚洲成人免费在线| 26uuu欧美日本| 欧美日韩一级大片网址| 国产在线精品一区二区不卡了| 午夜视频在线观看一区| 香蕉成人伊视频在线观看| 亚洲一二三四区不卡| 日韩国产一区二| 午夜精品福利一区二区三区蜜桃| 国产欧美va欧美不卡在线| 精品久久久久香蕉网| 亚洲国产激情av| 天堂影院一区二区| 亚洲成a人v欧美综合天堂| 亚洲综合激情另类小说区| 国产午夜精品一区二区三区视频 | 欧美视频中文字幕| 色综合天天综合在线视频| 91黄色免费版| 精品成人免费观看| 亚洲精品视频一区| 精品一区二区免费看| 成人的网站免费观看| 99re亚洲国产精品| 欧美一区二区三区四区高清| 国产亚洲一区二区三区| 国产欧美精品区一区二区三区| 国产欧美一区二区精品性色超碰| 日韩写真欧美这视频| 26uuuu精品一区二区| 亚洲精品在线电影| 亚洲欧美日韩国产综合在线|