www.久久久久|狼友网站av天堂|精品国产无码a片|一级av色欲av|91在线播放视频|亚洲无码主播在线|国产精品草久在线|明星AV网站在线|污污内射久久一区|婷婷综合视频网站

當前位置:首頁 > > 充電吧
[導讀]Composer?是PHP的一個包依賴管理工具,類似Ruby中的RubyGems或者Node中的NPM,它并非官方,但現(xiàn)在已經(jīng)非常流行。此文并不介紹如何使用Composer,而是關注于它的autolo

Composer?是PHP的一個包依賴管理工具,類似Ruby中的RubyGems或者Node中的NPM,它并非官方,但現(xiàn)在已經(jīng)非常流行。此文并不介紹如何使用Composer,而是關注于它的autoload的內(nèi)容吧。

舉例來說,假設我們的項目想要使用?monolog?這個日志工具,就需要在composer.json里告訴composer我們需要它:

{
??"require":?{
????"monolog/monolog":?"1.*"
??}
}

之后執(zhí)行:

php composer.phar install

好,現(xiàn)在安裝完了,該怎么使用呢?Composer自動生成了一個autoload文件,你只需要引用它

require '/path/to/vendor/autoload.php';

然后就可以非常方便的去使用第三方的類庫了,是不是感覺很棒?。τ谖覀冃枰膍onolog,就可以這樣用了:

use?MonologLogger;
use?MonologHandlerStreamHandler;

//?create?a?log?channel
$log?=?new?Logger('name');
$log->pushHandler(new?StreamHandler('/path/to/log/log_name.log',?Logger::WARNING));

//?add?records?to?the?log
$log->addWarning('Foo');
$log->addError('Bar');

在這個過程中,Composer做了什么呢?它生成了一個autoloader,再根據(jù)各個包自己的autoload配置,從而幫我們進行自動加載的工作。(如果對autoload這部分內(nèi)容不太了解,可以看我之前的?一篇文章

)接下來讓我們看看Composer是怎么做的吧。

對于第三方包的自動加載,Composer提供了四種方式的支持,分別是 PSR-0和PSR-4的自動加載(我的一篇文章也有介紹過它們),生成class-map,和直接包含files的方式。

PSR-4是composer推薦使用的一種方式,因為它更易使用并能帶來更簡潔的目錄結(jié)構(gòu)。在composer.json里是這樣進行配置的:

{
????"autoload":?{
????????"psr-4":?{
????????????"Foo\":?"src/",
????????}
????}
}

key和value就定義出了namespace以及到相應path的映射。按照PSR-4的規(guī)則,當試圖自動加載?"Foo\Bar\Baz"?這個class時,會去尋找?"src/Bar/Baz.php"?這個文件,如果它存在則進行加載。注意,?"Foo\"

并沒有出現(xiàn)在文件路徑中,這是與PSR-0不同的一點,如果PSR-0有此配置,那么會去尋找

"src/Foo/Bar/Baz.php"

這個文件。

另外注意PSR-4和PSR-0的配置里,"Foo\"結(jié)尾的命名空間分隔符必須加上并且進行轉(zhuǎn)義,以防出現(xiàn)"Foo"匹配到了"FooBar"這樣的意外發(fā)生。

在composer安裝或更新完之后,psr-4的配置換被轉(zhuǎn)換成namespace為key,dir path為value的Map的形式,并寫入生成的?vendor/composer/autoload_psr4.php?文件之中。

{
????"autoload":?{
????????"psr-0":?{
????????????"Foo\":?"src/",
????????}
????}
}

最終這個配置也以Map的形式寫入生成的

vendor/composer/autoload_namespaces.php

文件之中。

Class-map方式,則是通過配置指定的目錄或文件,然后在Composer安裝或更新時,它會掃描指定目錄下以.php或.inc結(jié)尾的文件中的class,生成class到指定file path的映射,并加入新生成的?vendor/composer/autoload_classmap.php?文件中,。

{
????"autoload":?{
????????"classmap":?["src/",?"lib/",?"Something.php"]
????}
}

例如src/下有一個BaseController類,那么在autoload_classmap.php文件中,就會生成這樣的配置:

'BaseController' => $baseDir . '/src/BaseController.php'

Files方式,就是手動指定供直接加載的文件。比如說我們有一系列全局的helper functions,可以放到一個helper文件里然后直接進行加載

{
????"autoload":?{
????????"files":?["src/MyLibrary/functions.php"]
????}
}

它會生成一個array,包含這些配置中指定的files,再寫入新生成的

vendor/composer/autoload_files.php

文件中,以供autoloader直接進行加載。

下面來看看composer autoload的代碼吧

?$path)?{
??????$loader->set($namespace,?$path);
??}

??$map?=?require?__DIR__?.?'/autoload_psr4.php';
??foreach?($map?as?$namespace?=>?$path)?{
??????$loader->setPsr4($namespace,?$path);
??}

??$classMap?=?require?__DIR__?.?'/autoload_classmap.php';
??if?($classMap)?{
??????$loader->addClassMap($classMap);
??}

??$loader->register(true);

??$includeFiles?=?require?__DIR__?.?'/autoload_files.php';
??foreach?($includeFiles?as?$file)?{
??????composerRequire73612b48e6c3d0de8d56e03dece61d11($file);
??}

??return?$loader;
????}
}

function?composerRequire73612b48e6c3d0de8d56e03dece61d11($file)
{
????require?$file;
}

首先初始化ClassLoader類,然后依次用上面提到的4種加載方式來注冊/直接加載,ClassLoader的一些核心代碼如下:

/**
???*?@param?array?$classMap?Class?to?filename?map
???*/
??public?function?addClassMap(array?$classMap)
??{
????if?($this->classMap)?{
??????$this->classMap?=?array_merge($this->classMap,?$classMap);
????}?else?{
??????$this->classMap?=?$classMap;
????}
??}

??/**
???*?Registers?a?set?of?PSR-0?directories?for?a?given?prefix,
???*?replacing?any?others?previously?set?for?this?prefix.
???*
???*?@param?string	???$prefix?The?prefix
???*?@param?array|string?$paths??The?PSR-0?base?directories
???*/
??public?function?set($prefix,?$paths)
??{
????if?(!$prefix)?{
??????$this->fallbackDirsPsr0?=?(array)?$paths;
????}?else?{
??????$this->prefixesPsr0[$prefix[0]][$prefix]?=?(array)?$paths;
????}
??}

??/**
???*?Registers?a?set?of?PSR-4?directories?for?a?given?namespace,
???*?replacing?any?others?previously?set?for?this?namespace.
???*
???*?@param?string	???$prefix?The?prefix/namespace,?with?trailing?'\'
???*?@param?array|string?$paths??The?PSR-4?base?directories
???*
???*?@throws?InvalidArgumentException
???*/
??public?function?setPsr4($prefix,?$paths)
??{
????if?(!$prefix)?{
??????$this->fallbackDirsPsr4?=?(array)?$paths;
????}?else?{
??????$length?=?strlen($prefix);
??????if?('\'?!==?$prefix[$length?-?1])?{
????????throw?new?InvalidArgumentException("A?non-empty?PSR-4?prefix?must?end?with?a?namespace?separator.");
??????}
??????$this->prefixLengthsPsr4[$prefix[0]][$prefix]?=?$length;
??????$this->prefixDirsPsr4[$prefix]?=?(array)?$paths;
????}
??}

??/**
???*?Registers?this?instance?as?an?autoloader.
???*
???*?@param?bool?$prepend?Whether?to?prepend?the?autoloader?or?not
???*/
??public?function?register($prepend?=?false)
??{
????spl_autoload_register(array($this,?'loadClass'),?true,?$prepend);
??}

??/**
???*?Loads?the?given?class?or?interface.
???*
???*?@param??string	$class?The?name?of?the?class
???*?@return?bool|null?True?if?loaded,?null?otherwise
???*/
??public?function?loadClass($class)
??{
????if?($file?=?$this->findFile($class))?{
??????includeFile($file);

??????return?true;
????}
??}

??/**
???*?Finds?the?path?to?the?file?where?the?class?is?defined.
???*
???*?@param?string?$class?The?name?of?the?class
???*
???*?@return?string|false?The?path?if?found,?false?otherwise
???*/
??public?function?findFile($class)
??{
????//這是PHP5.3.0?-?5.3.2的一個bug??詳見https://bugs.php.net/50731
????if?('\'?==?$class[0])?{
??????$class?=?substr($class,?1);
????}

????//?class?map?方式的查找
????if?(isset($this->classMap[$class]))?{
??????return?$this->classMap[$class];
????}

????//psr-0/4方式的查找
????$file?=?$this->findFileWithExtension($class,?'.php');

????//?Search?for?Hack?files?if?we?are?running?on?HHVM
????if?($file?===?null?&&?defined('HHVM_VERSION'))?{
??????$file?=?$this->findFileWithExtension($class,?'.hh');
????}

????if?($file?===?null)?{
??????//?Remember?that?this?class?does?not?exist.
??????return?$this->classMap[$class]?=?false;
????}

????return?$file;
??}

??private?function?findFileWithExtension($class,?$ext)
??{
????//?PSR-4?lookup
????$logicalPathPsr4?=?strtr($class,?'\',?DIRECTORY_SEPARATOR)?.?$ext;

????$first?=?$class[0];
????if?(isset($this->prefixLengthsPsr4[$first]))?{
??????foreach?($this->prefixLengthsPsr4[$first]?as?$prefix?=>?$length)?{
????????if?(0?===?strpos($class,?$prefix))?{
??????????foreach?($this->prefixDirsPsr4[$prefix]?as?$dir)?{
????????????if?(file_exists($file?=?$dir?.?DIRECTORY_SEPARATOR?.?substr($logicalPathPsr4,?$length)))?{
??????????????return?$file;
????????????}
??????????}
????????}
??????}
????}

????//?PSR-4?fallback?dirs
????foreach?($this->fallbackDirsPsr4?as?$dir)?{
??????if?(file_exists($file?=?$dir?.?DIRECTORY_SEPARATOR?.?$logicalPathPsr4))?{
????????return?$file;
??????}
????}

????//?PSR-0?lookup
????if?(false?!==?$pos?=?strrpos($class,?'\'))?{
??????//?namespaced?class?name
??????$logicalPathPsr0?=?substr($logicalPathPsr4,?0,?$pos?+?1)
????????.?strtr(substr($logicalPathPsr4,?$pos?+?1),?'_',?DIRECTORY_SEPARATOR);
????}?else?{
??????//?PEAR-like?class?name
??????$logicalPathPsr0?=?strtr($class,?'_',?DIRECTORY_SEPARATOR)?.?$ext;
????}

????if?(isset($this->prefixesPsr0[$first]))?{
??????foreach?($this->prefixesPsr0[$first]?as?$prefix?=>?$dirs)?{
????????if?(0?===?strpos($class,?$prefix))?{
??????????foreach?($dirs?as?$dir)?{
????????????if?(file_exists($file?=?$dir?.?DIRECTORY_SEPARATOR?.?$logicalPathPsr0))?{
??????????????return?$file;
????????????}
??????????}
????????}
??????}
????}

????//?PSR-0?fallback?dirs
????foreach?($this->fallbackDirsPsr0?as?$dir)?{
??????if?(file_exists($file?=?$dir?.?DIRECTORY_SEPARATOR?.?$logicalPathPsr0))?{
????????return?$file;
??????}
????}

????//?PSR-0?include?paths.
????if?($this->useIncludePath?&&?$file?=?stream_resolve_include_path($logicalPathPsr0))?{
??????return?$file;
????}
??}


/**
?*?Scope?isolated?include.
?*
?*?Prevents?access?to?$this/self?from?included?files.
?*/
function?includeFile($file)
{
??include?$file;
}


如此最終實現(xiàn)的原理是在vendor目錄下的


return?ComposerAutoloaderInit5cbf6bb00ad8ca1716a58cda814c22a3::getLoader();

在getLoader中為ComposerAutoloadClassLoader();類填充了信息包括psr-0 psr-4等自動加載機制所需的消息然后調(diào)用

ComposerAutoloadClassLoader()的register函數(shù),進行sql_autoload_register的調(diào)用,這樣之后每當進行類加載的時候
依次在?psr4前綴中進行查找文件目錄,在psr4?fallback目錄中查找,在psr0前綴中查找目錄,在psr0?fallback中查找還有就是在psr0?include?path中進行查找文件




本站聲明: 本文章由作者或相關機構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點,本站亦不保證或承諾內(nèi)容真實性等。需要轉(zhuǎn)載請聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請及時聯(lián)系本站刪除。
換一批
延伸閱讀

LED驅(qū)動電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關鍵字: 驅(qū)動電源

在工業(yè)自動化蓬勃發(fā)展的當下,工業(yè)電機作為核心動力設備,其驅(qū)動電源的性能直接關系到整個系統(tǒng)的穩(wěn)定性和可靠性。其中,反電動勢抑制與過流保護是驅(qū)動電源設計中至關重要的兩個環(huán)節(jié),集成化方案的設計成為提升電機驅(qū)動性能的關鍵。

關鍵字: 工業(yè)電機 驅(qū)動電源

LED 驅(qū)動電源作為 LED 照明系統(tǒng)的 “心臟”,其穩(wěn)定性直接決定了整個照明設備的使用壽命。然而,在實際應用中,LED 驅(qū)動電源易損壞的問題卻十分常見,不僅增加了維護成本,還影響了用戶體驗。要解決這一問題,需從設計、生...

關鍵字: 驅(qū)動電源 照明系統(tǒng) 散熱

根據(jù)LED驅(qū)動電源的公式,電感內(nèi)電流波動大小和電感值成反比,輸出紋波和輸出電容值成反比。所以加大電感值和輸出電容值可以減小紋波。

關鍵字: LED 設計 驅(qū)動電源

電動汽車(EV)作為新能源汽車的重要代表,正逐漸成為全球汽車產(chǎn)業(yè)的重要發(fā)展方向。電動汽車的核心技術(shù)之一是電機驅(qū)動控制系統(tǒng),而絕緣柵雙極型晶體管(IGBT)作為電機驅(qū)動系統(tǒng)中的關鍵元件,其性能直接影響到電動汽車的動力性能和...

關鍵字: 電動汽車 新能源 驅(qū)動電源

在現(xiàn)代城市建設中,街道及停車場照明作為基礎設施的重要組成部分,其質(zhì)量和效率直接關系到城市的公共安全、居民生活質(zhì)量和能源利用效率。隨著科技的進步,高亮度白光發(fā)光二極管(LED)因其獨特的優(yōu)勢逐漸取代傳統(tǒng)光源,成為大功率區(qū)域...

關鍵字: 發(fā)光二極管 驅(qū)動電源 LED

LED通用照明設計工程師會遇到許多挑戰(zhàn),如功率密度、功率因數(shù)校正(PFC)、空間受限和可靠性等。

關鍵字: LED 驅(qū)動電源 功率因數(shù)校正

在LED照明技術(shù)日益普及的今天,LED驅(qū)動電源的電磁干擾(EMI)問題成為了一個不可忽視的挑戰(zhàn)。電磁干擾不僅會影響LED燈具的正常工作,還可能對周圍電子設備造成不利影響,甚至引發(fā)系統(tǒng)故障。因此,采取有效的硬件措施來解決L...

關鍵字: LED照明技術(shù) 電磁干擾 驅(qū)動電源

開關電源具有效率高的特性,而且開關電源的變壓器體積比串聯(lián)穩(wěn)壓型電源的要小得多,電源電路比較整潔,整機重量也有所下降,所以,現(xiàn)在的LED驅(qū)動電源

關鍵字: LED 驅(qū)動電源 開關電源

LED驅(qū)動電源是把電源供應轉(zhuǎn)換為特定的電壓電流以驅(qū)動LED發(fā)光的電壓轉(zhuǎn)換器,通常情況下:LED驅(qū)動電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關鍵字: LED 隧道燈 驅(qū)動電源
關閉