機制完全指南:從配置數(shù)組到依賴注入容器與默認配置)
后端Web框架【免費下載鏈接】yii2Yii 2: The Fast, Secure and Professional PHP Framework項目地址https://gitcode.com/gh_mirrors/yi/yii2點擊查看免費下載Yii 2 在創(chuàng)建新對象或初始化既有對象時廣泛使用配置信息configuration這一機制。本文以官方指南 docs/guide-ja/concept-configurations.md 為骨架結合倉庫中framework/BaseYii.php、framework/di/Container.php、framework/base/Component.php等源碼實現(xiàn)系統(tǒng)講解配置數(shù)組的格式、Yii::createObject()與Yii::configure()的工作方式、應用與組件配置、配置文件拆分、默認配置以及YII_ENV環(huán)境常量的實戰(zhàn)用法。讀完本文你將能夠熟練運用配置數(shù)組創(chuàng)建與定制任意對象并為你的應用搭建按環(huán)境切換的配置體系。配置信息是什么在 Yii 2 中配置信息configuration通常是一個 PHP 數(shù)組用于在創(chuàng)建新對象或初始化已有對象時指定要創(chuàng)建的對象的類名賦給對象屬性properties的初始值列表附加到對象事件events上的事件處理器列表附加到對象上的行為behaviors列表。最典型的用法是創(chuàng)建并初始化一個數(shù)據(jù)庫連接$config [ class yii\db\Connection, dsn mysql:host127.0.0.1;dbnamedemo, username root, password , charset utf8, ]; $db Yii::createObject($config);Yii::createObject()接收配置數(shù)組實例化數(shù)組中class指定的類然后使用配置數(shù)組的其余部分完成對象屬性、事件處理器和行為的初始化。如果對象已經(jīng)存在可以使用Yii::configure()用配置數(shù)組初始化對象的屬性Yii::configure($object, $config);注意此時配置數(shù)組中不能包含class元素。源碼層面的實現(xiàn)在 framework/BaseYii.php 中createObject()的實現(xiàn)邏輯如下public static function createObject($type, array $params []) { if (is_string($type)) { return static::$container-get($type, $params); } if (is_callable($type, true)) { return static::$container-invoke($type, $params); } if (!is_array($type)) { throw new InvalidConfigException(Unsupported configuration type: . gettype($type)); } if (isset($type[__class])) { $class $type[__class]; unset($type[__class], $type[class]); return static::$container-get($class, $params, $type); } if (isset($type[class])) { $class $type[class]; unset($type[class]); return static::$container-get($class, $params, $type); } throw new InvalidConfigException(Object configuration must be an array containing a class or __class element.); }可見它支持三種入?yún)⑿问筋惷址苯咏唤o$container-get()創(chuàng)建實例配置數(shù)組要求包含class或__class元素其余鍵值對作為對象配置傳入PHP 可調用對象callable交由$container-invoke()執(zhí)行。當傳入空數(shù)組或不支持的null時會拋出yii\base\InvalidConfigException。這一點在測試 tests/framework/BaseYiiTest.php 中有明確斷言。而 framework/BaseYii.php 中的configure()則更簡單直接——它遍歷配置數(shù)組將每個鍵值對賦值給對象的同名屬性public static function configure($object, $properties) { foreach ($properties as $name $value) { $object-$name $value; } return $object; }配置信息的格式配置數(shù)組的正式格式可以描述如下[ class ClassName, propertyName propertyValue, on eventName $eventHandler, as behaviorName $behaviorConfig, ]其中各元素含義如下元素含義class要創(chuàng)建的對象的完整類名fully qualified class namepropertyName指定名字的屬性的初始值鍵是屬性名值是對應的初始值。只有公共成員變量以及由 getter/setter 定義的屬性才能被設置on eventName指定將何種處理器附加到對象的事件上。數(shù)組鍵的格式是on后接事件名處理器支持的格式詳見事件一節(jié)as behaviorName指定將何種行為附加到對象上。數(shù)組鍵格式是as后接行為名$behaviorConfig的值本身又是一個配置數(shù)組用來創(chuàng)建該行為下面是一個同時包含初始屬性值、事件處理器和行為配置的完整示例[ class app\components\SearchEngine, apiKey xxxxxxxx, on search function ($event) { Yii::info(Keyword searched: . $event-keyword); }, as indexer [ class app\components\IndexerBehavior, // ... 行為屬性初始值 ... ], ]底層是如何識別on與as前綴的配置之所以能支持事件與行為關鍵在于 framework/base/Component.php 的__set()魔術方法。當通過配置給組件賦值時它按以下順序處理若存在set開頭的 setter 方法則作為屬性賦值若鍵名以on開頭則調用$this-on(trim(substr($name, 3)), $value)附加事件處理器若鍵名以as開頭則解析行為配置支持行為實例、閉包、帶class/__class的配置數(shù)組或行為類名字符串并調用attachBehavior()附加行為否則回退為給已附加行為的同名屬性賦值。因此只有當對象是yii\base\Component或其子類時on ...與as ...語法才有效而class與普通屬性賦值則對所有對象通用。配置信息的使用場景配置信息在 Yii 的許多地方都會用到。開頭已經(jīng)展示了用Yii::createObject()按配置創(chuàng)建對象的方式下面重點講解兩個最主要的用途應用Application配置與組件Component配置。應用配置應用的配置信息可能是 Yii 中最復雜的數(shù)組之一因為yii\web\Application類擁有大量可配置的屬性和事件。更重要的是它的components屬性可以接收一組用于創(chuàng)建應用組件的配置數(shù)組。下面是基礎項目模板應用配置文件的核心部分$config [ id basic, basePath dirname(__DIR__), extensions require __DIR__ . /../vendor/yiisoft/extensions.php, components [ cache [ class yii\caching\FileCache, ], mailer [ class yii\symfonymailer\Mailer, ], log [ class yii\log\Dispatcher, traceLevel YII_DEBUG ? 3 : 0, targets [ [ class yii\log\FileTarget, ], ], ], db [ class yii\db\Connection, dsn mysql:hostlocalhost;dbnamestay2, username root, password , charset utf8, ], ], ];這個配置數(shù)組沒有class鍵因為在入口腳本中類名已經(jīng)給出(new yii\web\Application($config))-run();關于應用components屬性的詳細配置請參考應用與服務定位器兩節(jié)。從源碼看framework/base/Application.php 在構造函數(shù)中會把核心組件與自定義組件做一次合并如果某個核心組件如db、cache沒有出現(xiàn)在配置中就使用默認配置如果出現(xiàn)了但沒寫class則自動補上核心組件的類名。這也是為什么配置中經(jīng)??梢允÷詂lass的原因。2.0.11 起支持在應用配置中定制依賴注入容器從 2.0.11 版本開始應用配置支持通過container屬性配置依賴注入容器$config [ id basic, basePath dirname(__DIR__), extensions require __DIR__ . /../vendor/yiisoft/extensions.php, container [ definitions [ yii\widgets\LinkPager [maxButtonCount 5] ], singletons [ // 依賴注入容器單例的配置 ] ] ];definitions與singletons配置數(shù)組支持的值及其示例可閱讀依賴注入容器一節(jié)的高級實際用法。在 framework/base/Application.php 中container鍵會先被取出并交給setContainer($config[container])處理隨后從剩余配置中移除因此它不會作為普通屬性賦值。組件Widget配置使用組件widget時通常需要借助配置數(shù)組來定制組件屬性。yii\base\Widget::widget()與yii\base\Widget::begin()都接收配置數(shù)組。例如use yii\widgets\Menu; echo Menu::widget([ activateItems false, items [ [label 主頁, url [site/index]], [label 產(chǎn)品, url [product/index]], [label 登錄, url [site/login], visible Yii::$app-user-isGuest], ], ]);以上代碼創(chuàng)建了一個Menu組件將其activateItems屬性初始化為false并配置items屬性以展示菜單項。由于類名已經(jīng)由Menu::widget()給出因此配置數(shù)組中不應再包含class鍵。配置文件Configuration Files當配置變得非常復雜時通常的做法是把它放到一個或多個配置文件中。配置文件是一個返回配置數(shù)組的 PHP 文件。例如可以把應用配置放在名為web.php的文件里return [ id basic, basePath dirname(__DIR__), extensions require __DIR__ . /../vendor/yiisoft/extensions.php, components require __DIR__ . /components.php, ];由于components部分也很復雜可以像上面這樣把它拆到獨立的components.php文件中再在web.php中通過require引入。components.php的內(nèi)容大致如下return [ cache [ class yii\caching\FileCache, ], mailer [ class yii\symfonymailer\Mailer, ], log [ class yii\log\Dispatcher, traceLevel YII_DEBUG ? 3 : 0, targets [ [ class yii\log\FileTarget, ], ], ], db [ class yii\db\Connection, dsn mysql:hostlocalhost;dbnamestay2, username root, password , charset utf8, ], ];要取得配置文件中的配置只需require它即可$config require path/to/web.php; (new yii\web\Application($config))-run();這種按職責拆分 require組合的模式是 Yii 項目中組織復雜配置的標準做法也是后續(xù)按環(huán)境組合配置見下文環(huán)境常量一節(jié)的基礎。默認配置Default ConfigurationsYii::createObject()基于依賴注入容器實現(xiàn)。因此可以為一類對象指定所謂默認配置default configuration凡是經(jīng)由Yii::createObject()創(chuàng)建的該類實例都會自動套用該配置。默認配置通常在引導bootstrapping階段通過Yii::$container-set()注冊\Yii::$container-set(yii\widgets\LinkPager, [ maxButtonCount 5, ]);上面的例子把所有鏈接分頁器yii\widgets\LinkPager的頁碼按鈕數(shù)從默認的 10 個調整為最多 5 個。不使用默認配置的話你就必須在每個使用分頁器的地方手動設置maxButtonCount。maxButtonCount的默認值10定義在 framework/widgets/LinkPager.php。容器是如何實現(xiàn)默認配置的在 framework/di/Container.php 中set()把類的定義規(guī)范化后存入_definitions當createObject()經(jīng)由get()獲取對象時framework/di/Container.php 會取出該定義把其中的配置與調用方傳入的配置用array_merge合并調用方的配置優(yōu)先級更高再執(zhí)行構建。這意味著通過Yii::$container-set()注冊的默認配置會對所有該類的實例生效具體某次調用傳入的配置可以覆蓋默認值set()還支持注冊別名、接口綁定以及構造參數(shù)$params容器會利用反射解析構造函數(shù)依賴并自動注入見 framework/di/Container.php 的build()方法。對象的生命周期配置如何生效還與對象的構造方式有關。framework/base/BaseObject.php 的構造函數(shù)揭示了 Yii 對象的初始化順序public function __construct($config []) { if (!empty($config)) { Yii::configure($this, $config); } $this-init(); }即先執(zhí)行構造函數(shù) → 按配置初始化屬性 → 調用init()方法。文檔建議所有需要額外初始化的邏輯寫在init()中因為此時配置已經(jīng)應用完畢。而 framework/base/Application.php 中應用的init()會觸發(fā)bootstrap()從而加載擴展并啟動引導組件——這正是Yii::$container-set()這類默認配置注冊代碼的典型執(zhí)行時機。環(huán)境常量Environment Constants配置往往隨應用運行環(huán)境而變化。例如開發(fā)環(huán)境使用名為mydb_dev的數(shù)據(jù)庫而生產(chǎn)服務器上使用mydb_prod。為了便于切換環(huán)境Yii 提供了YII_ENV常量可以在應用的入口腳本中定義defined(YII_ENV) or define(YII_ENV, dev);YII_ENV可以定義為以下值值說明prod生產(chǎn)環(huán)境。常量YII_ENV_PROD為true。未特別定義時這是YII_ENV的默認值dev開發(fā)環(huán)境。常量YII_ENV_DEV為truetest測試環(huán)境。常量YII_ENV_TEST為true這些環(huán)境常量由 framework/BaseYii.php 在框架加載時統(tǒng)一計算并定義YII_ENV默認prodYII_ENV_PROD/YII_ENV_DEV/YII_ENV_TEST則分別由YII_ENV prod或dev、test推導而來。注意這里YII_ENV的值不限于這三者你完全可以定義staging等其他值此時三個YII_ENV_*布爾常量均為false可在配置中自行判斷。利用環(huán)境常量可以根據(jù)當前環(huán)境條件式地定制配置。例如在開發(fā)環(huán)境啟用調試工具欄與調試器時應用配置可包含如下代碼$config [...]; if (YII_ENV_DEV) { // 為 dev 環(huán)境調整配置 $config[bootstrap][] debug; $config[modules][debug] yii\debug\Module; } return $config;小結與實踐建議回顧本文核心要點配置數(shù)組是 Yii 2 創(chuàng)建/初始化對象的標準手段包含class、屬性值、on 事件、as 行為四類元素Yii::createObject()內(nèi)部走 DI 容器負責按配置創(chuàng)建對象Yii::configure()負責按配置初始化已有對象應用配置與組件配置是配置最典型的兩大場景前者通過components批量注冊組件2.0.11 起還支持通過container配置 DI 容器復雜配置應拆分為多個配置文件用require組合便于維護通過Yii::$container-set()注冊的默認配置可以對一類對象統(tǒng)一生效利用YII_ENV環(huán)境常量實現(xiàn)開發(fā)、測試、生產(chǎn)環(huán)境的條件化配置。在動手實踐時建議從配置文件拆分 環(huán)境常量組合 默認配置三者入手構建你的應用配置體系把公共配置放進common.php把環(huán)境差異放進web.php/console.php在入口腳本中按YII_ENV決定加載哪一套。相關實現(xiàn)細節(jié)與測試用例可分別參考 framework/di/Container.php、framework/base/BaseObject.php 與 tests/framework/BaseYiiTest.php。贊分享后端Web框架【免費下載鏈接】yii2Yii 2: The Fast, Secure and Professional PHP Framework項目地址https://gitcode.com/gh_mirrors/yi/yii2點擊查看免費下載相關推薦Yii 2 配置Configuration完全指南配置格式、應用與 Widget 配置、默認配置及多環(huán)境管理Yii 2 配置Configuration完全指南配置格式、應用與 Widget 配置、默認配置及多環(huán)境管理 配置Configuration在 Yii后端Web框架Yii 2 依賴注入容器DI Container完全指南從四種注入方式到實戰(zhàn)配置Yii 2 依賴注入容器DI Container完全指南從四種注入方式到實戰(zhàn)配置 導讀 依賴注入容器Dependency Injection Conta后端Web框架Yii 2 配置機制完全指南配置格式、應用與組件配置、默認配置及 YII_ENV 環(huán)境切換Yii 2 配置機制完全指南配置格式、應用與組件配置、默認配置及 YII_ENV 環(huán)境切換 Yii 2 框架中配置Configuration是創(chuàng)建對象、后端Web框架創(chuàng)作聲明:本文部分內(nèi)容由AI輔助生成(AIGC),僅供參考