讓你深刻了解yii2的九個概念
與 laravel 相較,Yii2 將配置(依賴關係定義)外化,用行為(更類似於 python 中的織入)類,彌補
Trait
的一些不足,好處是可以動態擴充套件動作。至於事件處理則大同小異,有趣的是在命名上,yii2 借用了jquery
事件系統的那一套,on,off,trigger
。當然也相同之處,比如應用都是建立在容器之上。相比其它的面向領域,面向介面程式設計,Yii2 使用模組,來分層,分中心小應用,細化大架構。而getter/setter
,及過濾器,java 痕跡太明顯。
元件 Component
- Yii 應用的主要基石。是
yii\base\Component
類或其子類的例項- 主要由 屬性(Property),事件(Event),行為(Behavior)三個功能組成
- 比常規的物件(Object)稍微重量級,要使用額外的記憶體和 CPU 時間來處理 事件 和 行為
- 不需要使用事件和行為時,繼承
yii\base\Object
, 支援屬性(Property)功能
- 重寫 Component 或 Object
- 永遠在重寫的構造方法結尾處呼叫一下父類的構造方法
- 傳入 $config 作為構造器方法最後一個引數,由父構造方呼叫,在應用配置之前初始化
- 若重寫了 BaseObject::init () 方法,確保在 init 方法的開頭處呼叫了父類的 init 方法
- 元件例項化 2 種方式
- 例項化元件類,new 元件類, 元件普通引數 + 元件配置屬性引數
- 通過
\Yii::createObject
- 第一個陣列引數 class 關聯元件類名,後續關聯元素依次為元件例項屬性及值
- 第二陣列引數 元件的普通引數
Yii::createObject()
基於依賴注入容器實現
yii\base\BaseObject
類執行時的生命週期- 構造方法內的預初始化過程
- 通過 $config 配置物件
- 在 init () 方法內進行初始化後的收尾工作
- 物件方法呼叫,上述步驟皆在物件的構造方法內完成,即獲得例項就已經初始化,可供使用
屬性 Property
Yii
引入yii\base\Object
的基類, 支援基於類內的getter
和setter
(讀取器和設定器)方法來定義屬性- getter 和 setter 定義屬性規則和限制
- 這類屬性的名字是不區分大小寫,源於 PHP 方法名是不區分大小寫
- 若此類屬性名和類成員變數相同,以後者為準
- 該類屬性不支援可見性(訪問限制)
- 這類屬性的 getter 和 setter 方法只能定義為非靜態的
- 對不確定有無魔術方法
(getter 或 setter
的屬性正常呼叫property_exists()
將不會生效- 若真有此需求,應用
canGetProperty()
或canSetProperty()
- 若真有此需求,應用
事件 Events
-
事件可以將自定義程式碼 “注入” 到現有程式碼中的特定執行點
- 附加自定義程式碼到某個事件,當這個事件被觸發時,這些程式碼就會自動執行
-
事件處理器
Event Handlers
- 事件處理器是一個 PHP 回撥函式,也可以是一個可呼叫物件
- 字串形式指定的 PHP 全域性函式 ,如
'trim'
- 物件名和方法名陣列形式指定的物件方法,
[$object, $method]
- 類名和方法名陣列形式指定的靜態類方法,如
[$class, $method]
- 匿名函式,如
function ($event) { ... }
-
事件物件 $event
event name
:事件名event sender
:呼叫 trigger () 方法的物件custom data
附加事件處理器時傳入的資料,預設為空
-
附加事件處理器
- 呼叫元件類的 on 方法,諸如 \yii\base\Component::on ()
public void on ( $name, $handler, $data = null, $append = true )
-
事件處理器順序(Event Handler Order)
- 當事件被觸發,已附加的處理器將按附加次序依次呼叫
- 若需要停止同一事件的後續處理器的呼叫,可設定 event 引數的
yii\base\Event::event引數的‘yii\base\Event::handled
屬性為真 - 第四個引數 $append 為假時,可在處理器佇列最前面插入新處理器
-
觸發事件(Triggering Events)
- 事件通過呼叫
yii\base\Component::trigger()
方法觸發public void trigger ( $name, yii\base\Event $event = null )
- 推薦使用類常量來表示事件名,事件物件必須是
yii\base\Event
類或其子類的例項
- 事件通過呼叫
-
移除事件處理器(Detaching Event Handlers)
public boolean off ( $name, $handler = null )
-
類級別的事件處理器
- 應用場景 想要一個類的所有例項都響應一個被觸發的事件
- 呼叫靜態方法
yii\base\Event::on()
在類級別附加處理器- 在事件處理器內,通過 $event->sender 獲取觸發事件的物件
- 當物件觸發事件時,它首先呼叫例項級別的處理器,然後才會呼叫類級別處理器
- 靜態方法 yii\base\Event::trigger () 來觸發一個類級別事件,移除用 off
- 移除簽名
public static boolean off ( $class, $name, $handler = null )
-
介面事件
- 呼叫
Event::on()
並將介面類名作為第一個引數 - 可在實現介面事件類中觸發這個事件,但不能讓所有實現這個介面的類都觸發事件
- 呼叫
-
全域性事件
- 需要一個全域性可訪問的單例,如應用例項
- 事件觸發者不呼叫其自身的 trigger () 方法,而是呼叫單例的 trigger () 方法來觸發全域性事件
- 優點 是當附加處理器到一個物件要觸發的事件時, 不需要產生該物件
-
萬用字元事件 Wildcard Events
- foo.event.* , 萬用字元模式支援例項 或類級別的事件
行為
-
行為是
yii\base\Behavior
或其子類的例項,也稱為 mixins, 類似於原生的 Trait- 作用 無須改變類繼承關係即可增強一個已有的 元件 類功能
- 當行為附加到元件後,它將 “注入” 它的方法和屬性到元件
- 行為通過元件能響應被觸發的事件,從而自定義或調整元件正常執行的程式碼
-
處理事件
- 讓行為響應對應元件的事件觸發, 應覆寫
yii\base\Behavior::events()
方法- 行為的 events () 方法返回事件列表和相應的處理器,指定事件處理器格式如下
- 指向行為類的方法名的字串
- 物件或類名和方法名的陣列,如 [$object, ‘methodName’];
- 匿名方法
- 行為的 events () 方法返回事件列表和相應的處理器,指定事件處理器格式如下
- 讓行為響應對應元件的事件觸發, 應覆寫
-
附加行為
- 靜態附加行為
- 覆寫行為要附加的元件類的 behaviors () 方法即可
- behaviors () 方法返回行為配置列表,每個行為配置可以是行為類名也可以是配置陣列
- 過指定行為配置陣列相應的鍵可以給行為關聯一個名稱,這種行為稱為命名行為,反之匿名行為或命名行為
- 動態附加行為
- 在對應元件裡呼叫
yii\base\Component::attachBehavior()
方法 - 或
yii\base\Component::attachBehaviors()
方法一次附加多個行為public void attachBehaviors (array $behaviors )
- 通過配置附加行為
- [‘as myBehavior2’ => MyBehavior::className()]
- 在對應元件裡呼叫
- 靜態附加行為
-
使用行為
- 必須先將為附加到 component 類或其子類元件,然後可通過訪問元件訪問行為的公共成員變數
- 若兩個行為都定義了一樣的屬性或方法,並且它們都附加到同一個元件,先附加者有優先權
- 附加行為到元件時的命名行為,可以使用這個名稱來訪問行為物件,
$component->getBehavior('myBehavior');
- 獲取附加到這個元件的所有行為
getBehaviors()
-
移除行為
- 可以呼叫
yii\base\Component::detachBehavior()
方法用行為相關聯的名字實現
- 可以呼叫
-
Yii2 內建行為類
yii\behaviors\TimestampBehavior
在 Active Record 儲存時自動更新它的時間戳屬性yii\behaviors\BlameableBehavior
使用當前使用者 ID 自動填充指定的屬性yii\behaviors\SluggableBehavior
自動填充指定的屬性,其值可以在 URL 中用作 slugyii\behaviors\AttributeBehavior
在發生特定事件時自動為 ActiveRecord 物件的一個或多個屬性 指定一個指定的值yii2tech\ar\softdelete\SoftDeleteBehavior
提供軟刪除和軟恢復 ActiveRecord 的 方法yii2tech\ar\position\PositionBehavior
允許通過提供重新排序方法來 管理整數字段中的記錄順序
-
行為 VS Traits
- 都將自己的屬性和方法 “注入” 到主類中,二者類似互補類而非替代類
- 行為類優點
- 行為類像普通類支援繼承
- 行為無須修改元件類就可動態附加到元件或移除
- 行為是可配置的,而 traits 則不可行
- 行為可以通過響應事件來定製元件的程式碼執行
- traits 的原因
- Traits 比行為更有效,因為行為是既需要時間又需要記憶體的物件
- 名稱衝突解決方案
- 當附屬於同一組件的不同行為之間可能存在名稱衝突時, 通過優先考慮附加到該元件的行為
- 不同 traits 引起的名稱衝突需要通過 重新命名受影響的屬性或方法進行手動解決
配置 Configurations
-
概述
- 在建立新物件和初始化已存在物件時使用配置
- 配置通常包含被建立物件的類名和一組將要賦值給物件 屬性的初始值
- 亦可包含一組將被附加到物件事件上的控制代碼,和一組將被附加到物件上的行為
-
使用
- Yii::createObject () 方法接受一個配置陣列並根據陣列中指定的類名建立物件
- 對於已存在的物件,可以使用
Yii::configure()
方法根據配置去初始化其屬性Yii::configure($object, $config)
- 注若配置一個已存在的物件,那麼配置陣列中不應該包含指定類名的 class 元素
-
配置的格式
class
元素指定了將要建立的物件的完全限定類名propertyName
元素指定了物件屬性的初始值,鍵名是屬性名,值是該屬性對應的初始值- 只有公共成員變數以及通過 getter/setter 定義的 屬性可以被配置
on eventName
元素指定了附加到物件事件上的控制代碼,陣列的鍵名由 on 字首加事件名組成as behaviorName
元素指定了附加到物件的行為,值表示建立行為的配置資訊
-
應用的配置
- application 類擁有很多可配置的屬性和事件
- components 屬性可以接收配置陣列並通過應用註冊為元件
- yii2.0.11+ 系統配置支援使用 container 屬性來配置依賴注入容器
-
小部件的配置
yii\base\Widget::widget()
和yii\base\Widget::begin()
方法都可以用來建立小部件- 通過用配置來自定義其屬性,注意 給出類名的情況下,配置陣列不需要再包含 class 鍵
-
預設配置
Yii::createObject()
方法基於依賴注入容器實現- 使用
Yii::creatObject()
建立物件時,可以附加一系列預設配置到指定類的任何例項 - 預設配置可以在入口指令碼 中呼叫
Yii::$container->set()
來定義
別名
- 設定與解析
- 使用
Yii::setAlias()
來給檔案路徑或 URL 定義別名 - 呼叫
Yii::getAlias()
命令來解析根別名到對應的檔案路徑或 URL
- 使用
- 應用提供了一個名為 aliases 的可寫屬性, 可在應用配置中設定它
- 使用別名 Yii 內路徑屬性接受別名
- Yii2 預定義別名
- 擴充套件的別名
- 一個通過 Composer 安裝的 擴充套件 都自動添加了一個別名,定義於引導啟動階段
類的自動載入
- Yii 自動載入器
- 每個類都必須置於名稱空間之下
- 每個類都必須儲存為單獨檔案
- 要將自定義名稱空間新增到自動載入器,需要使用 Yii::setAlias () 為名稱空間的根目錄定義別名
- 類對映表
- 類對映表功能,建立一個從類的名字到類檔案路徑的對映
- 當自動載入器載入一個檔案時,他首先檢查對映表裡有沒有該類
- 可以用
Yii::$classMap
方法向對映表中新增類
- 其他自動載入器
- 在其他自動載入器安裝成功之後, 再包含 Yii.php (yii 的自動載入器)
- 目的使 Yii 成為第一個響應任何類自動載入請求的自動載入器
- Yii 自動載入器支援自動載入擴充套件的類,需要在 composer.json 檔案里正確地定義 autoload 部分
服務定位器(Service Locator)
- 定義
- 提供各種應用所需的服務(或元件)的物件
- 在服務定位器中, 每個元件都只有一個單獨的例項,並通過 ID 唯一地標識
- 在 Yii 中,服務定位器是
yii\di\ServiceLocator
或其子類的一個例項
- 應用場景
- 最常用的服務定位器是 application(應用)物件,可以通過 \Yii::$app 訪問
- 每個模組物件本身也是一個服務定位器,模板可視為一個子應用
- 使用服務定位器
- 註冊相關元件
- 通過
yii\di\ServiceLocator::set()
方法進行相關元件註冊。 public void set ( $id, $definition )
$definition
可以是類名,配置陣列,php 可呼叫物件,或者本身就是一個物件例項
- 通過
- 允許通過元件 ID 像訪問一個屬性值那樣訪問一個元件
- 服務定位器會返回同一個元件的單例
yii\di\ServiceLocator::has()
檢查某元件 ID 是否被註冊yii\di\ServiceLocator::get()
- 註冊相關元件
- 遍歷樹(Tree traversal)
- 模組允許任意巢狀;Yii 應用程式本質上是一個模組樹
- 模組中元件的配置決不會與來自父模組中元件的配置合併
依賴注入容器
- 依賴注入容器是一個物件,知道怎樣初始化並配置物件及其依賴的所有物件
Yii 通過 yii\di\Container
類提供 DI 容器特性- 構造方法注入
- 容器會嘗試獲取它所依賴的類或介面的例項,然後通過構造器將其注入新的物件
- 方法注入
- 可以提供僅由類的單個方法需要的依賴關係
- Setter 和屬性注入
- Setter 和屬性注入是通過配置提供,該配置會提供給容器用於通過相應的 Setter 或屬性注入依賴
- PHP 回撥注入 (PHP Callable Injection)
- 容器將使用已註冊的 PHP 回撥來構建類的新例項
- 構造方法注入
yii\di\Container::get()
方法將其第三個引數作為配置陣列應用於正在建立的物件 如果該類實現yii\base\Configurable
介面(例如 yii\base\BaseObject),則配置陣列將作為最後一個引數傳遞給類建構函式
- 註冊依賴關係
- 用
yii\di\Container::set()
註冊依賴關係 - 註冊會用到一個依賴關係名稱和一個依賴關係的定義, 鍵值對可遞迴,方便容器管理例項,類似 laravel 的別名系統
- 依賴關係名稱可為類名,介面名或一個別名,依賴關係的定義可以是類名,配置陣列,一個 PHP 回撥
- 通過
set()
註冊的依賴關係,在每次使用時都會產生一個新例項 - 使用
yii\di\Container::setSingleton()
註冊一個單例的依賴關係
- 用
- 解析依賴關係
- 依賴關係解析是遞迴式進行
- 註冊依賴關係後,容器會自動解析依賴關係, 將依賴例項化並注入新建立的物件
- 依賴關係名,可以是通過
set()
或setSingleton()
註冊的,也可以是一個類構造器引數列表和一個configuration
用於配置新建立的物件
- 使用依賴注入
- 在應用程式的入口指令碼中引入
Yii.php
檔案時,Yii
就建立了一個 DI 容器 - 該 DI 容器可以通過
Yii::$container
訪問 - 當呼叫
Yii::createObject()
時,此方法實際上會呼叫這個容器的 get () 方法建立新物件 - 在部件呼叫中給出的屬性將始終覆蓋 DI 容器中的定義,若報錯無法被例項化,需要告知容器如何處理依賴關係
- 在應用程式的入口指令碼中引入
- 高階實用性
- 可一次配置多個定義 , 將配置陣列傳遞給
setDefinitions()
或setSingletons()
方法 - 配置陣列格式
key
:類名稱,介面名稱或別名value
:與 class 關聯的定義,class關聯的定義,‘identifies
引數值將傳遞給 set () 方法- 可以選擇將依賴項的建構函式引數作為第三個引數
Instance::of('tempFileStorage')
符號,Container
將隱含地提供一個用tempFileStorage
名稱註冊的依賴項- 應用場景 內部配置依賴項
- 通過 set () 註冊的依賴項將在每次需要時例項化
- 可一次配置多個定義 , 將配置陣列傳遞給
- 依賴關係註冊使用
- 應用開發在入口註冊依賴關係
- 擴充套件開發,則在擴充套件引導類中註冊依賴關係
- 小結
- Yii 在依賴住入(DI)容器之上實現了它的服務定位器
- 當一個服務定位器嘗試建立一個新的物件例項時,它會把呼叫轉發到 DI 容器
更多學習內容可以訪問【對標大廠】精品PHP架構師教程目錄大全,只要你能看完保證薪資上升一個臺階(持續更新)
還有更多進階學習資料領取噢進階PHP月薪30k>>>架構師成長路線【視訊、面試文件免費獲取】