[Yii2.0] 以Yii 2.0風格加載自定義類或命名空間 [配置使用Yii2 autoloader]

Yii 2.0最顯著的特徵之一就是引入了命名空間,所以對於自定義類的引入方式也同以前有所不一樣。這篇文章討論一下如何利用Yii 2.0的自動加載機制,向系統中引入自定義類和命名空間。本文旨在拋磚引玉,若是有理解不當敬請指正,歡迎你們把本身的方法拿出來分享。
咱們但願被引入的類應該達成一下兩點:php

  1. 在應用中的任這裏輸入代碼意位置可使用該類名或命名空間,而不用顯式調用require()/include()。
  2. 利用Yii的autoloader,僅在類被調用時加載,以遵循Yii按需加載的原則,節省資源。

咱們使用Yii 2.0基礎模板做爲演示環境,項目根目錄命名爲basic(後文中會寫成/),這是根目錄結構: web

basic
├── assets
├── commands
├── config
├── controllers
├── mail
├── models
├── runtime
├── tests
├── vendor
├── views
└── web

加載自定義類

I. 定義類文件

創建目錄 /libs 並創建文件Freedom.php。數組

<?php class Freedom { public static function yell() { echo "I am FREE!"; } }

II. 向Yii::$classMap添加映射

打開配置文件/config/web.php,在文件頭部向[[Yii::$classMap]]屬性添加類映射。app

<?php ... Yii::$classMap['Freedom'] = '@app/libs/Freedom.php'; ... $config = [ ... ]; return $config;

注意: 不要對[[Yii::$classMap]]使用=直接賦值,由於該屬性中定義了Yii的一些核心類映射,直接賦值會致使這些映射丟失而Yii autoloader加載不到核心類。No zuo no die don't try.dom

III. 使用自定義類

見證奇蹟的時刻。在系統中嘗試調用這個類,咱們使用SiteController::actionIndex()爲例。yii

<?php ... use Freedom; // 別忘了導入這個類,或者在後面調用的時候使用"\Freedom"。 class SiteController extends Controller ... public function actionIndex() { Freedom::yell(); } }

好了,刷新一下試試。ui

IV. 若是你還關心爲何

那如今咱們來須要介紹一下[[Yii::$classMap]]到底是個毛。這貨其實是一個關聯數組,數組鍵爲「去掉前導反斜線的徹底權限定類名」,對應值爲定義了該類的文件路徑,其中文件路徑支持路徑別名。在代碼中調用到還沒有加載的類時,Yii的audoloader會掃描這個屬性以得到須要加載的類文件名。spa

因此,咱們把剛剛定義的類加入到這個映射數組中,它就能夠被Yii延遲加載了。事實上咱們能夠在任何位置添加這個映射,只要在目標類被調用以前就能夠。應用的主配置文件是一個比較理想的位置,由於配置文件加載在Yii.php以後,能夠在其中訪問到Yii類(有興趣的同窗能夠去看一下入口腳本),並且配置數據能夠集中在一個文件裏。code

另外,因爲咱們定義的類在根命名空間下,因此「去掉前導反斜線的徹底權限定類名」就只剩下Freedom了。若是你的類使用了命名空間,只須要在數組鍵裏寫上徹底限定名稱就好了(e.g. ['custom\classes\Freedom'])。資源


加載整個命名空間

有時候咱們須要寫一組相互關聯的類,若是這些類存在依賴關係的話像上面這樣給每一個類配置映射會……非(jue)常(b)不(gao)體(si)面(ren)。若是你定義命名空間下的類時遵循 PSR-4 標準,咱們能夠一次引入整個命名空間。
此次咱們要使用的屬性是[[\yii\base\Application::$aliases]]。它也是一個關聯數組,將一個路徑別名映射到一個目錄或者另外一個已經存在的路徑別名。其中數組鍵是要指定的別名,對應值是目標路徑。
咱們只須要在創建一個命名空間別名,把它映射到保存這個命名空間下全部類的根目錄,就能夠了。固然這個根目錄如下的文件結構和類定義要遵循PSR-4,否則autoloader是找不到對應文件的。
試一下:

I. 定義命名空間和類文件

咱們決定在/libs/vendors目錄下定義一組以命名空間組織的類,其根目錄命名爲free-classes,這組類的所有在命名空間free_classes下。注意這裏我故意使根目錄名與根命名空間名不一致以表示映射根目錄不必定要和命名空間同名。
建立文件/libs/vendors/free-classes/persons/Slave.php,沒有目錄請自行建立。

<?php namespace free_classes\persons; class Slave { public static function isFree() { var_dump("I'm FREE now, thank you!"); } }

建立文件/libs/vendors/free-classes/vehicles/cars/Porsche.php

<?php namespace free_classes\vehicles\cars; class Porsche { public static function isFree() { var_dump('Are you kidding?!'); } }

注意: free-classes如下的目錄名和結構都要遵循PSR-4標準。

II. 配置[[\yii\web\Application::$aliases]]

這裏要說一下,若是咱們的命名空間爲namespace\subnamespace,那麼咱們應該設置的路徑別名就是@namespace/subnamespace(詳解參照 PSR-4 )。
打開配置文件/config/web.php,配置Application的aliaes屬性:

<?php Yii::$classMap['Freedom'] = '@app/libs/Freedom.php'; ... $config = [ 'id' => 'basic', ... 'aliases' => [ '@free_classes' => '@app/libs/vendors/free-classes' ], ... ]; return $config;

III. 使用命名空間下的類

又要見證奇蹟了,仍是選在SiteController::actionIndex()裏。

<?php ... use free_classes\persons\Slave; // 仍是別忘了導入 use free_classes\vehicles\cars\Porsche; class SiteController extends Controller ... public function actionIndex() { // Freedom::yell(); Slave::isFree(); Porsche::isFree(); } }

刷新一下;-)

相關文章
相關標籤/搜索