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