詳解 composer 的自動加載機制

composer是一個用PHP開發(fā)的用來管理項目依賴的工具泥耀,當你在項目中聲明了依賴關(guān)系后琅束,composer可以自動幫你下載和安裝這些依賴庫,并實現(xiàn)自動加載代碼。

安裝composer
1.下載安裝腳本,這里把安裝腳本保存為 composer-setup.php

[root@localhost composer]# php -r "copy('https://install.phpcomposer.com/installer', 'composer-setup.php');"
[root@localhost composer]# ls
composer-setup.php

2.然后執(zhí)行運行安裝腳本跌造,然后會生成一個可執(zhí)行的phar包文件composer.phar(類似java中的.jar包)

[root@localhost composer]# php composer-setup.php 
All settings correct for using Composer
Downloading...

Composer (version 1.8.5) successfully installed to: /root/composer/composer.phar
Use it: php composer.phar

[root@localhost composer]# ls
composer.phar  composer-setup.php

3.執(zhí)行命令: php composer.phar, 顯示如下信息說明安裝成功,注意最好不要使用root賬戶來執(zhí)行composer命令,否則會報警告:

Do not run Composer as root/super user! See https://getcomposer.org/root for details


[root@localhost composer]# php composer.phar 
Do not run Composer as root/super user! See https://getcomposer.org/root for details
   ______
  / ____/___  ____ ___  ____  ____  ________  _____
 / /   / __ \/ __ `__ \/ __ \/ __ \/ ___/ _ \/ ___/
/ /___/ /_/ / / / / / / /_/ / /_/ (__  )  __/ /
\____/\____/_/ /_/ /_/ .___/\____/____/\___/_/
                    /_/
Composer version 1.8.5 2019-04-09 17:46:47

Usage:
  command [options] [arguments]

Options:
  -h, --help                     Display this help message
.....
  1. 如果想讓composer在任意目錄下都可以執(zhí)行吼鱼,可以執(zhí)行命令:mv composer.phar /usr/local/bin/composer 蓬豁,將 composer.phar 放到系統(tǒng)環(huán)境變量之下并重命名為composer, 之后便可以在任意目錄使用 composer 來代替 php composer.phar 命令
[root@localhost composer]# mv composer.phar /usr/local/bin/composer
[root@localhost composer]# cd ~
[root@localhost ~]# composer
Do not run Composer as root/super user! See https://getcomposer.org/root for details
   ______
  / ____/___  ____ ___  ____  ____  ________  _____
 / /   / __ \/ __ `__ \/ __ \/ __ \/ ___/ _ \/ ___/
/ /___/ /_/ / / / / / / /_/ / /_/ (__  )  __/ /
\____/\____/_/ /_/ /_/ .___/\____/____/\___/_/
.....

配置composer使用國內(nèi)鏡像庫

由于國內(nèi)特殊的網(wǎng)絡(luò)環(huán)境,訪問國外的官方鏡像庫往往速度很慢菇肃,甚至無響應(yīng)地粪,所以我們配置使用composer中文網(wǎng)(http://www.phpcomposer.com)提供的國內(nèi)鏡像庫,執(zhí)行以下命令即可

[lf@localhost root]$ composer config -g repo.packagist composer https://packagist.phpcomposer.com

簡單的composer.json

假設(shè)我們現(xiàn)在的項目根目錄為demo琐谤,并且我們的項目依賴 monolog(https://github.com/Seldaek/monolog) 這個php日志庫,這時我們可以在項目根目錄建立一個 composer.json 文件蟆技,并輸入以下內(nèi)容:

{
    "require": {
        "monolog/monolog": "1.0.*"
    }
}

然后輸入命令 composer install,composer會幫我們自動下載monolog庫斗忌,一般依賴庫會默認放在項目的vendor目錄下

[root@localhost demo]# ls
composer.json
[root@localhost demo]# composer install
Do not run Composer as root/super user! See https://getcomposer.org/root for details
Loading composer repositories with package information
Updating dependencies (including require-dev)
Package operations: 1 install, 0 updates, 0 removals
    Failed to download monolog/monolog from dist: The zip extension and unzip command are both missing, skipping.
The php.ini used by your command-line PHP is: /etc/php.ini
    Now trying to download from source
  - Installing monolog/monolog (1.0.2): Cloning b704c49a30
Writing lock file
Generating autoload files
[root@localhost demo]# ls
composer.json  composer.lock  vendor
composer的自動加載

composer不僅僅幫我們處理依賴质礼,還幫我們實現(xiàn)了自動加載。在vendor目錄下有一個autoload.php, 只要在我們的項目中引入這個文件就可以自動加載依賴庫织阳。

項目根目錄下新建一個index.php, 并輸入以下測試代碼:

<?php
require 'vendor/autoload.php';
 
use Monolog\Logger;
use Monolog\Handler\StreamHandler;
 
$log = new Logger('demo');
$log->pushHandler(new StreamHandler('app.log', Logger::WARNING));
$log->addWarning("this is a warning log!");

測試是否運行正常:

[root@localhost demo]# php index.php 
[root@localhost demo]# ls
app.log  composer.json  composer.lock  index.php  vendor
[root@localhost demo]# cat app.log 
[2021-11-03 00:32:27] demo.WARNING: this is a warning log! [] []

可以看到monolog庫完全不需要我們手動去加載眶蕉,只需要使用正確的命名空間,composer的自動加載機制會幫我們找到對應(yīng)的文件并加載唧躲。
對于依賴庫造挽,composer幫我們處理好了自動加載,那對于我們自己的項目文件該怎么實現(xiàn)自動加載呢弄痹,比如現(xiàn)在在我的項目根目下創(chuàng)建一個 controllers 目錄存放控制器饭入,并在該目錄下新建一個Controller.php, 代碼如下:

<?php
namespace controllers;
 
class Controller
{
    public function test()
    {
        echo "Controller::test\n";
    }
}

現(xiàn)在如何在index.php中自動加載這個 Controller 類呢,如果我們直接在index.php寫

<?php
require 'vendor/autoload.php';
use controllers\Controller;
 
$c = new Controller();
$c->test();

上面代碼肯定是無法找到Controller類的:

[root@localhost demo]# php index.php 
PHP Fatal error:  Uncaught Error: Class 'controllers\Controller' not found in /root/demo/index.php:6
Stack trace:
#0 {main}
  thrown in /root/demo/index.php on line 6

要想解決上述這個問題我們首先需要了解下composer的自動加載機制界酒。
composer支持四種自動加載的方式:PSR-0 / PSR-4 /Classmap / Files , 其中 PSR-4 是當前推薦的加載方式圣拄。

什么是 PSR ?

PSR 是 PHP Standards Recommendations(PHP 標準建議)的縮寫,這是一個叫做 PHP Framework Interop Group(http://www.php-fig.org/) 的組織所推出的關(guān)于PHP編程方面的一些標準建議毁欣,這個組織的成員包括一些知名的框架和項目庇谆,比如 CakePHP,Drupal凭疮,Magento饭耳,Symfony,Yii framework执解,Zend Framework 2等等寞肖,當然也包括這里說的 composer,該組織曾推出了一系列的 PSR, 具體的有哪些請參考 http://www.php-fig.org/psr/ 衰腌, 其中 PSR-0 (http://www.php-fig.org/psr/psr-0/)和 PSR-4(http://www.php-fig.org/psr/psr-4/)是關(guān)于自動加載方面做出的一些規(guī)范

  1. Files 是最簡單的加載方式新蟆,這種方式不管加載的文件是否用到始終都會加載,而不是按需加載

修改項目根目下的composer.json, 加入 "autoload" 項:

{
    "require": {
        "monolog/monolog": "1.0.*"
    },
    "autoload": {
        "files": ["controllers/Controller.php"]
    }
}

需要加載哪個文件右蕊,直接寫入文件路徑即可琼稻,路徑相對項目的根目錄。然后執(zhí)行composer dump-autoload饶囚,該命令可以遍歷我們項目根目錄以及各依賴庫下的 composer.json 文件然后重新生成 vendor/composer/autoload_* 跟自動加載相關(guān)的配置文件

[root@localhost demo]# composer dump-autoload
Do not run Composer as root/super user! See https://getcomposer.org/root for details
Generating autoload files

此時composer會幫我們更新自動加載相關(guān)的配置文件帕翻,composer dump-autoload 之后composer會把配置值寫入與 Files加載方式對應(yīng)的 vendor/composer/autoload_files.php 配置文件中:

[root@localhost demo]# cat vendor/composer/autoload_files.php 
<?php

// autoload_files.php @generated by Composer

$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);

return array(
    '0b001b283842589bdffd092a1d29de66' => $baseDir . '/controllers/Controller.php',
);

此時再運行index.php就一切正常了

[root@localhost demo]# php index.php
Controller::test
  1. Classmap 加載方式也很簡單鸠补,composer會搜尋我們指定的目錄或文件,并把搜尋到的結(jié)果寫到Classmap對應(yīng)的 vendor/composer/autoload_classmap.php 配置文件中嘀掸。 修改composer.json :
{
    "require": {
        "monolog/monolog": "1.0.*"
    },
    "autoload": {
        "classmap": ["controllers/"]
    }
}

以上配置會讓composer搜尋 controllers 目錄下的所有類紫岩,并生成配置文件,同樣先 composer dump-autoload 下:

[root@localhost demo]# composer dump-autoload
Do not run Composer as root/super user! See https://getcomposer.org/root for details
Generating autoload files

[root@localhost demo]# cat vendor/composer/autoload_classmap.php 
<?php

// autoload_classmap.php @generated by Composer

$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);

return array(
    'controllers\\Controller' => $baseDir . '/controllers/Controller.php',
);

此時發(fā)現(xiàn)之前生成的 vendor/composer/autoload_files.php 配置文件也被 composer 刪除了(由于項目中沒再使用到Files的加載方式)

[root@localhost demo]# ll vendor/composer/
總用量 44
-rw-r--r-- 1 root root   222 11月  03 01:59 autoload_classmap.php
-rw-r--r-- 1 root root   210 11月  03 01:59 autoload_namespaces.php
-rw-r--r-- 1 root root   143 11月  03 01:59 autoload_psr4.php
-rw-r--r-- 1 root root  1762 11月  03 01:59 autoload_real.php
-rw-r--r-- 1 root root   867 11月  03 01:59 autoload_static.php
-rw-r--r-- 1 root root 13451 11月  03 01:59 ClassLoader.php
-rw-r--r-- 1 root root  1375 11月  03 01:59 installed.json
-rw-r--r-- 1 root root  1070 11月  03 01:59 LICENSE
測試結(jié)果:

[root@localhost demo]# php index.php 
Controller::test
  1. PSR-0 睬塌,這種加載方式已經(jīng)過時泉蝌,所以不推薦在新項目中使用,請用 PSR-4 來代替它衫仑。
    修改composer.json 如下, 然后執(zhí)行composer dump-autoload
{
    "require": {
        "monolog/monolog": "1.0.*"
    },
    "autoload": {
        "psr-0": {"controllers\\": ""}
    }
}

以上配置的意思是指定 controllers命名空間 所在的父級目錄梨与,由于controllers命名空間所在的父級目錄就是項目根目錄堕花, 所以配置值用 "" 文狱,composer dump-autoload后配置會寫入 PSR-0對應(yīng)的 vendor/composer/autoload_namespaces.php 配置文件中,而且從配置文件中可以看到之前使用的 monolog 也是使用 遵循PSR-0 規(guī)范的自動加載

[root@localhost demo]# composer dump-autoload
Do not run Composer as root/super user! See https://getcomposer.org/root for details
Generating autoload files

[root@localhost demo]# cat vendor/composer/autoload_namespaces.php
<?php

// autoload_namespaces.php @generated by Composer

$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);

return array(
    'controllers\\' => array($baseDir . '/'),
    'Monolog' => array($vendorDir . '/monolog/monolog/src'),
);
[root@localhost demo]# php index.php 
Controller::test
  1. PSR-4 是 PSR-0 的升級版缘挽,是目前推薦的自動加載方式瞄崇,這種方式使用的是按需加載。
    修改composer.json 如下:
{
    "require": {
        "monolog/monolog": "1.0.*"
    },
    "autoload": {
        "psr-4": {"controllers\\": "controllers/"}
    }
}

注意和PSR-0 的 composer.json 做對比壕曼,PSR-4 和 PSR-0 的主要區(qū)別是苏研,PSR-4指定的就當作當前命名空間的目錄, 而PSR-0 指定的是當前命名空間的父目錄腮郊。composer dump-autoload 一下摹蘑, 配置會寫入PSR-4對應(yīng)的 vendor/composer/autoload_psr4.php 文件中

[root@localhost demo]# cat vendor/composer/autoload_psr4.php 
<?php

// autoload_psr4.php @generated by Composer

$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);

return array(
    'controllers\\' => array($baseDir . '/controllers'),
);

[root@localhost demo]# php index.php 
Controller::test
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市轧飞,隨后出現(xiàn)的幾起案子衅鹿,更是在濱河造成了極大的恐慌,老刑警劉巖过咬,帶你破解...
    沈念sama閱讀 221,430評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件大渤,死亡現(xiàn)場離奇詭異,居然都是意外死亡掸绞,警方通過查閱死者的電腦和手機泵三,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,406評論 3 398
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來衔掸,“玉大人烫幕,你說我怎么就攤上這事〕ㄓ常” “怎么了较曼?”我有些...
    開封第一講書人閱讀 167,834評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長驱显。 經(jīng)常有香客問我诗芜,道長瞳抓,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,543評論 1 296
  • 正文 為了忘掉前任伏恐,我火速辦了婚禮孩哑,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘翠桦。我一直安慰自己横蜒,他們只是感情好,可當我...
    茶點故事閱讀 68,547評論 6 397
  • 文/花漫 我一把揭開白布销凑。 她就那樣靜靜地躺著丛晌,像睡著了一般。 火紅的嫁衣襯著肌膚如雪斗幼。 梳的紋絲不亂的頭發(fā)上澎蛛,一...
    開封第一講書人閱讀 52,196評論 1 308
  • 那天,我揣著相機與錄音蜕窿,去河邊找鬼谋逻。 笑死,一個胖子當著我的面吹牛桐经,可吹牛的內(nèi)容都是我干的毁兆。 我是一名探鬼主播,決...
    沈念sama閱讀 40,776評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼阴挣,長吁一口氣:“原來是場噩夢啊……” “哼气堕!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起畔咧,我...
    開封第一講書人閱讀 39,671評論 0 276
  • 序言:老撾萬榮一對情侶失蹤茎芭,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后盒卸,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體骗爆,經(jīng)...
    沈念sama閱讀 46,221評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,303評論 3 340
  • 正文 我和宋清朗相戀三年蔽介,在試婚紗的時候發(fā)現(xiàn)自己被綠了摘投。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,444評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡虹蓄,死狀恐怖犀呼,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情薇组,我是刑警寧澤外臂,帶...
    沈念sama閱讀 36,134評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站律胀,受9級特大地震影響宋光,放射性物質(zhì)發(fā)生泄漏貌矿。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,810評論 3 333
  • 文/蒙蒙 一罪佳、第九天 我趴在偏房一處隱蔽的房頂上張望逛漫。 院中可真熱鬧,春花似錦赘艳、人聲如沸酌毡。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,285評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽枷踏。三九已至,卻和暖如春掰曾,著一層夾襖步出監(jiān)牢的瞬間旭蠕,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,399評論 1 272
  • 我被黑心中介騙來泰國打工婴梧, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留下梢,地道東北人客蹋。 一個月前我還...
    沈念sama閱讀 48,837評論 3 376
  • 正文 我出身青樓塞蹭,卻偏偏與公主長得像,于是被迫代替她去往敵國和親讶坯。 傳聞我的和親對象是個殘疾皇子番电,可洞房花燭夜當晚...
    茶點故事閱讀 45,455評論 2 359

推薦閱讀更多精彩內(nèi)容