這次給大家帶來Yii2架構類自動載入使用詳解,Yii2架構類自動載入的注意事項有哪些,下面就是實戰案例,一起來看一下。
在yii中,程式中需要使用到的類無需事先載入其類檔案,在使用的時候才自動定位類檔案位置並載入之,這麼高效的運行方式得益於yii的類自動載入機制。
Yii的類自動載入實際上使用的是PHP的類自動載入,所以先來看看PHP的類自動載入。在PHP中,當程式中使用的類未載入時,在報錯之前會先調用魔術方法autoload()
,所以我們可以重寫autoload()方法,定義當一個類找不到的時候怎麼去根據類名稱找到對應的檔案並載入它。其中autoload()方法被稱為類自動載入器。當我們需要多個類自動載入器的時候,我們可以使用spl_autoload_register()
方法代替autoload()來註冊多個類自動載入器,這樣就相當於有多個autoload()方法。spl_autoload_register()方法會把所有註冊的類自動載入器存入一個隊列中,你可以通過設定它的第三個參數為true來指定某個載入器放到隊列的最前面以確保它最先被調用。Yii的類自動載入機制就是基於spl_autoload_register()方法的。
Yii的類自動載入機制要從它的入口檔案index.php說起了,該檔案源碼如下:
<?phpdefined('YII_DEBUG') or define('YII_DEBUG', true);//運行模式defined('YII_ENV') or define('YII_ENV', 'dev');//運行環境require(DIR . '/../../vendor/autoload.php');//composer的類自動負載檔案require(DIR . '/../../vendor/yiisoft/yii2/Yii.php');//yii的工具類檔案(包含了yii類自動載入)require(DIR . '/../../common/config/bootstrap.php');//主要用於執行一些yii應用引導的代碼require(DIR . '/../config/bootstrap.php');$config = yii\helpers\ArrayHelper::merge( require(DIR . '/../../common/config/main.php'), require(DIR . '/../../common/config/main-local.php'), require(DIR . '/../config/main.php'), require(DIR . '/../config/main-local.php'));(new yii\web\Application($config))->run();
檔案中第4、5行代碼分別引入了composer的類自動負載檔案和yii的工具類檔案Yii.php,Yii.php檔案源碼如下:
require(DIR . '/BaseYii.php');class Yii extends \yii\BaseYii{}spl_autoload_register(['Yii', 'autoload'], true, true);//註冊yii的類自動載入器Yii::$classMap = require(DIR . '/classes.php');//引入類名到類檔案路徑的映射Yii::$container = new yii\di\Container();
這個檔案定義了Yii類繼承自\yii\BaseYii,代碼的第6行引入了classes.php檔案,該檔案源碼:
return [ 'yii\base\Action' => YII2_PATH . '/base/Action.php', 'yii\base\ActionEvent' => YII2_PATH . '/base/ActionEvent.php', ....//省略n多元素 'yii\widgets\Pjax' => YII2_PATH . '/widgets/Pjax.php', 'yii\widgets\PjaxAsset' => YII2_PATH . '/widgets/PjaxAsset.php', 'yii\widgets\Spaceless' => YII2_PATH . '/widgets/Spaceless.php',];
通過查看其源碼可以看到,這個檔案返回了一個從類名稱到類檔案路徑的映射數組。這個數組被賦值給Yii::$classMap。代碼的第7行調用了spl_autoload_register()
方法註冊了一個類自動載入器,這個類載入器為Yii::autoload()
,這就是yii的類載入器了。同時這裡通過把spl_autoload_register()
方法第三個參數賦值為true,把yii的類載入器放在了載入器隊列的最前面,所以當訪問一個未載入的類的時候,yii的類自動載入器會最先被調用。
下面我們就來看看yii的類自動載入器Yii::autoload()到底做了些什麼,這個方法實際上在yii\BaseYii類中,源碼如下:
/** * 類自動載入器 * @param type $className:要載入的類的名稱 * @return type * @throws UnknownClassException */public static function autoload($className){ if (isset(static::$classMap[$className])) {//要載入的類在 類名=>類檔案路徑 映射中找到 $classFile = static::$classMap[$className]; if ($classFile[0] === '@') {//若類檔案路徑使用了別名,進行別名解析獲得完整路徑 $classFile = static::getAlias($classFile); } } elseif (strpos($className, '\\') !== false) {//類名需要包含'\'才符合規範 $classFile = static::getAlias('@' . str_replace('\\', '/', $className) . '.php', false);//進行別名解析(說明類名必須以有效根別名打頭) if ($classFile === false || !is_file($classFile)) { return; } } else { return; } include($classFile);//引入需要載入的類檔案 if (YII_DEBUG && !class_exists($className, false) && !interface_exists($className, false) && !trait_exists($className, false)) { throw new UnknownClassException("Unable to find '$className' in file: $classFile. Namespace missing?"); }}
這個方法首先會根據需要載入的類的名稱去Yii::$classMap
這個映射數組中尋找,若存在則引入對應的類檔案,不存在則進行別名解析得到完整檔案路徑,這裡也說明若使用的類不在YII::$classMap中事先定義,則類名必須以有效根別名打頭,否則無法找到對應檔案。
就這樣,在yii中無需在程式中事先載入一大堆可能會使用到的類檔案,當使用到某個類的時候,yii的類自動載入器就會自動進行載入了,高效又便捷!
相信看了本文案例你已經掌握了方法,更多精彩請關注php中文網其它相關文章!
推薦閱讀:
PHP+ajax實現擷取新聞資料案例詳解
php curl批處理實現可控並發非同步作業案例詳解