讓你深入瞭解yii2的九個概念

與 laravel 相較,Yii2 將配置(依賴關係定義)外化,用行爲(更相似於 python 中的織入)類,彌補Trait的一些不足,好處是能夠動態擴展動做。至於事件處理則大同小異,有趣的是在命名上,yii2 借用了jquery事件系統的那一套,on,off,trigger。固然也相同之處,好比應用都是創建在容器之上。相比其它的面向領域,面向接口編程,Yii2 使用模塊,來分層,分中心小應用,細化大架構。而getter/setter,及過濾器,java 痕跡太明顯。php

組件 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()基於依賴注入容器實現java

  • yii\base\BaseObject 類執行時的生命週期
    • 構造方法內的預初始化過程
    • 經過 $config 配置對象
    • 在 init () 方法內進行初始化後的收尾工做
    • 對象方法調用,上述步驟皆在對象的構造方法內完成,即得到實例就已經初始化,可供使用

屬性 Property

  • Yii引入yii\base\Object的基類, 支持基於類內的getter和 setter(讀取器和設定器)方法來定義屬性
  • getter 和 setter 定義屬性規則和限制
    • 這類屬性的名字是不區分大小寫,源於 PHP 方法名是不區分大小寫
    • 若此類屬性名和類成員變量相同,之後者爲準
    • 該類屬性不支持可見性(訪問限制)
    • 這類屬性的 getter 和 setter 方法只能定義爲非靜態的
    • 對不肯定有無魔術方法(getter 或 setter 的屬性正常調用 property_exists()將不會生效
      • 若真有此需求,應用canGetProperty()canSetProperty()

事件 Events

  • 事件能夠將自定義代碼 「注入」 到現有代碼中的特定執行點python

    • 附加自定義代碼到某個事件,當這個事件被觸發時,這些代碼就會自動執行
  • 事件處理器Event Handlersjquery

    • 事件處理器是一個 PHP 回調函數,也能夠是一個可調用對象
    • 字符串形式指定的 PHP 全局函數 ,如'trim'
    • 對象名和方法名數組形式指定的對象方法,[$object, $method]
    • 類名和方法名數組形式指定的靜態類方法,如[$class, $method]
    • 匿名函數,如function ($event) { ... }
  • 事件對象 $eventlaravel

    • 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)json

    • 事件經過調用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 )
  • 類級別的事件處理器yii2

    • 應用場景 想要一個類的全部實例都響應一個被觸發的事件
    • 調用靜態方法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’];
        • 匿名方法
  • 附加行爲

    • 靜態附加行爲
      • 覆寫行爲要附加的組件類的 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 中用做 slug
    • yii\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>>>架構師成長路線【視頻、面試文檔免費獲取】

相關文章
相關標籤/搜索