Yii2框架類(lèi)自動(dòng)加載機(jī)制實(shí)例分析
本文實(shí)例講述了Yii2框架類(lèi)自動(dòng)加載機(jī)制。分享給大家供大家參考,具體如下:
在yii中,程序中需要使用到的類(lèi)無(wú)需事先加載其類(lèi)文件,在使用的時(shí)候才自動(dòng)定位類(lèi)文件位置并加載之,這么高效的運(yùn)行方式得益于yii的類(lèi)自動(dòng)加載機(jī)制。
Yii的類(lèi)自動(dòng)加載實(shí)際上使用的是PHP的類(lèi)自動(dòng)加載,所以先來(lái)看看PHP的類(lèi)自動(dòng)加載。在PHP中,當(dāng)程序中使用的類(lèi)未加載時(shí),在報(bào)錯(cuò)之前會(huì)先調(diào)用魔術(shù)方法__autoload(),所以我們可以重寫(xiě)__autoload()方法,定義當(dāng)一個(gè)類(lèi)找不到的時(shí)候怎么去根據(jù)類(lèi)名稱找到對(duì)應(yīng)的文件并加載它。其中__autoload()方法被稱為類(lèi)自動(dòng)加載器。當(dāng)我們需要多個(gè)類(lèi)自動(dòng)加載器的時(shí)候,我們可以使用spl_autoload_register()方法代替__autoload()來(lái)注冊(cè)多個(gè)類(lèi)自動(dòng)加載器,這樣就相當(dāng)于有多個(gè)__autoload()方法。spl_autoload_register()方法會(huì)把所有注冊(cè)的類(lèi)自動(dòng)加載器存入一個(gè)隊(duì)列中,你可以通過(guò)設(shè)置它的第三個(gè)參數(shù)為true來(lái)指定某個(gè)加載器放到隊(duì)列的最前面以確保它最先被調(diào)用。Yii的類(lèi)自動(dòng)加載機(jī)制就是基于spl_autoload_register()方法的。
Yii的類(lèi)自動(dòng)加載機(jī)制要從它的入口文件index.php說(shuō)起了,該文件源碼如下:
<?php
defined('YII_DEBUG') or define('YII_DEBUG', true);//運(yùn)行模式
defined('YII_ENV') or define('YII_ENV', 'dev');//運(yùn)行環(huán)境
require(__DIR__ . '/../../vendor/autoload.php');//composer的類(lèi)自動(dòng)加載文件
require(__DIR__ . '/../../vendor/yiisoft/yii2/Yii.php');//yii的工具類(lèi)文件(包含了yii類(lèi)自動(dòng)加載)
require(__DIR__ . '/../../common/config/bootstrap.php');//主要用于執(zhí)行一些yii應(yīng)用引導(dǎo)的代碼
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的類(lèi)自動(dòng)加載文件和yii的工具類(lèi)文件Yii.php,Yii.php文件源碼如下:
require(__DIR__ . '/BaseYii.php');
class Yii extends \yii\BaseYii
{
}
spl_autoload_register(['Yii', 'autoload'], true, true);//注冊(cè)yii的類(lèi)自動(dòng)加載器
Yii::$classMap = require(__DIR__ . '/classes.php');//引入類(lèi)名到類(lèi)文件路徑的映射
Yii::$container = new yii\di\Container();
這個(gè)文件定義了Yii類(lèi)繼承自\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', ];
通過(guò)查看其源碼可以看到,這個(gè)文件返回了一個(gè)從類(lèi)名稱到類(lèi)文件路徑的映射數(shù)組。這個(gè)數(shù)組被賦值給Yii::$classMap。代碼的第7行調(diào)用了spl_autoload_register()方法注冊(cè)了一個(gè)類(lèi)自動(dòng)加載器,這個(gè)類(lèi)加載器為Yii::autoload(),這就是yii的類(lèi)加載器了。同時(shí)這里通過(guò)把spl_autoload_register()方法第三個(gè)參數(shù)賦值為true,把yii的類(lèi)加載器放在了加載器隊(duì)列的最前面,所以當(dāng)訪問(wèn)一個(gè)未加載的類(lèi)的時(shí)候,yii的類(lèi)自動(dòng)加載器會(huì)最先被調(diào)用。
下面我們就來(lái)看看yii的類(lèi)自動(dòng)加載器Yii::autoload()到底做了些什么,這個(gè)方法實(shí)際上在yii\BaseYii類(lèi)中,源碼如下:
/**
* 類(lèi)自動(dòng)加載器
* @param type $className:要加載的類(lèi)的名稱
* @return type
* @throws UnknownClassException
*/
public static function autoload($className)
{
if (isset(static::$classMap[$className])) {//要加載的類(lèi)在 類(lèi)名=>類(lèi)文件路徑 映射中找到
$classFile = static::$classMap[$className];
if ($classFile[0] === '@') {//若類(lèi)文件路徑使用了別名,進(jìn)行別名解析獲得完整路徑
$classFile = static::getAlias($classFile);
}
} elseif (strpos($className, '\\') !== false) {//類(lèi)名需要包含'\'才符合規(guī)范
$classFile = static::getAlias('@' . str_replace('\\', '/', $className) . '.php', false);//進(jìn)行別名解析(說(shuō)明類(lèi)名必須以有效的根別名打頭)
if ($classFile === false || !is_file($classFile)) {
return;
}
} else {
return;
}
include($classFile);//引入需要加載的類(lèi)文件
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?");
}
}
這個(gè)方法首先會(huì)根據(jù)需要加載的類(lèi)的名稱去Yii::$classMap這個(gè)映射數(shù)組中查找,若存在則引入對(duì)應(yīng)的類(lèi)文件,不存在則進(jìn)行別名解析得到完整文件路徑,這里也說(shuō)明若使用的類(lèi)不在YII::$classMap中事先定義,則類(lèi)名必須以有效的根別名打頭,否則無(wú)法找到對(duì)應(yīng)文件。
就這樣,在yii中無(wú)需在程序中事先加載一大堆可能會(huì)使用到的類(lèi)文件,當(dāng)使用到某個(gè)類(lèi)的時(shí)候,yii的類(lèi)自動(dòng)加載器就會(huì)自動(dòng)進(jìn)行加載了,高效又便捷!
更多關(guān)于Yii相關(guān)內(nèi)容感興趣的讀者可查看本站專(zhuān)題:《Yii框架入門(mén)及常用技巧總結(jié)》、《php優(yōu)秀開(kāi)發(fā)框架總結(jié)》、《smarty模板入門(mén)基礎(chǔ)教程》、《php面向?qū)ο蟪绦蛟O(shè)計(jì)入門(mén)教程》、《php字符串(string)用法總結(jié)》、《php+mysql數(shù)據(jù)庫(kù)操作入門(mén)教程》及《php常見(jiàn)數(shù)據(jù)庫(kù)操作技巧匯總》
希望本文所述對(duì)大家基于Yii框架的PHP程序設(shè)計(jì)有所幫助。
相關(guān)文章
yiic命令時(shí)提示“php.exe”不是內(nèi)部或外部命令的解決方法
這篇文章主要介紹了yiic命令時(shí)提示“php.exe”不是內(nèi)部或外部命令的解決方法,針對(duì)環(huán)境變量的配置與Yii框架的配置文件修改來(lái)解決這一問(wèn)題,具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2014-12-12
ThinkPhP+Apache+PHPstorm整合框架流程圖解
這篇文章主要介紹了ThinkPhP+Apache+PHPstorm整合框架流程圖解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-11-11
使用Yii2實(shí)現(xiàn)主從數(shù)據(jù)庫(kù)設(shè)置
大家應(yīng)該都知道,當(dāng)項(xiàng)目做大了,數(shù)據(jù)庫(kù)主從還是不可少的。使用Yii框架開(kāi)發(fā),如何設(shè)置數(shù)據(jù)庫(kù)的主從呢?其實(shí)很簡(jiǎn)單。下面這篇文章就給大家詳細(xì)介紹了使用Yii2實(shí)現(xiàn)主從數(shù)據(jù)庫(kù)設(shè)置的方法,文中介紹的很詳細(xì),相信對(duì)大家的理解和學(xué)習(xí)很有幫助,下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。2016-11-11
Laravel如何實(shí)現(xiàn)自動(dòng)加載類(lèi)
今天小編就為大家整理了一篇Laravel如何實(shí)現(xiàn)自動(dòng)加載類(lèi)的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-10-10
CI框架學(xué)習(xí)筆記(二) -入口文件index.php
本文介紹的是CI框架的入口文件index.php的相關(guān)資料,需要的朋友可以參考下2014-10-10
Yii2.0小部件GridView(兩表聯(lián)查/搜索/分頁(yè))功能的實(shí)現(xiàn)代碼
這篇文章主要介紹了Yii2.0小部件GridView(兩表聯(lián)查/搜索/分頁(yè))功能的實(shí)現(xiàn)代碼,需要的朋友可以參考下2017-08-08
php調(diào)用快遞鳥(niǎo)接口實(shí)例代碼
這篇文章主要介紹了php調(diào)用快遞鳥(niǎo)接口實(shí)例代碼,需要的朋友可以參考下2017-10-10

