
composer是現代PHP的基石
現代高級編程語言,依賴管理工具是必不可少的。Java有Maven,Python有pip,Nodejs有npm, 而在composer出現之前,PHP只有被廣為詬病的Pear, 由於Pear實在太難用,很少PHP開發者用到這個工具。以致於PHP的開發生態很糟糕。
連一個像樣的依賴管理工具都沒有,讓PHP這門占據了web網站開發�主流市場的語言很尷尬。開發過程中,要用到第三方的類庫,需要去下載zip包,然后解壓,放到相應的目錄,處理好命名空間,自動加載的問題,如果這個第三方包還有其他依賴項,還要再次重復這個流程,看着隔壁家python和node.js一個命令行就搞定,顯得php開發人員的操作既原始又滑稽。
這場面,好比:

所幸,金光閃閃的composer駕着七彩祥雲來了,PHP終於有了真正意義的依賴管理工具。可以說,composer是現代PHP的基石。
composer解決了項目的依賴關系,且實現了自動加載。開發人員只需要幾個命令行,就能獲取其他開發者的包,PHP開發工作因此變得如同堆積木,可以根據業務的需求,快速方便地拆解組合代碼。
奇怪的是,即使compoer已經誕生好些年了,而且所有主流框架都支持composer,可竟然還有不少PHP開發者不用這個工具。甚至還有人覺得composer加大了PHP的學習難度。
持有這種想法的人,就好像是一輩子都用紙筆手工記賬,有朝一日,給他配置了電腦,跟他演示了excel是如何地強大。他不為新事物的強大感到震撼驚喜,而是蹙眉不滿地說:“這東西太難學了,我還是習慣用紙筆”。
對於持有這種想法的人,我只能兩手一攤。心態衰老的年輕人,如果他的內心一直在裝睡,任誰也叫不醒。但時代的步伐可不會因為他們的拉后腿而停止前進,只會把他們遠遠甩在身后...
初識composer
composer的安裝步驟,在composr中文社區有詳細的說明,點擊查看
安裝流程
安裝的流程很簡單,歸結為以下幾步:
php -r "copy('https://install.phpcomposer.com/installer', 'composer-setup.php');" # 下載安裝腳本 - composer-setup.php - 到當前目錄 php composer-setup.php # 執行安裝過程 php -r "unlink('composer-setup.php');" # 刪除安裝腳本 sudo mv composer.phar /usr/local/bin/composer # 全局安裝 composer config -g repo.packagist composer https://packagist.phpcomposer.com # 更換國內鏡像源
安裝完成后,查看composer版本

第一次使用
接下來,我們用composer來安裝第一個包
以monolog
包為例,這個包可以讓開發者很方便地將日記寫入到文件、數據庫或其他儲存介質中。
- 在項目根目錄新建
composer.json
文件,寫入以下內容
{
"require": { "monolog/monolog": "1.2.*" } }
- 執行
composer install
指令安裝包依賴

- 使用包進行開發

composer已經為我們下載了monolog
包,且生成了autoload.php
自動加載文件
新建monolog.php
文件,內容如下:
<?php require 'vendor/autoload.php'; use Monolog\Logger; use Monolog\Handler\StreamHandler; // create a log channel $log = new Logger('name'); $log->pushHandler(new StreamHandler('monolog.log', Logger::WARNING)); // add records to the log $log->warn('警告日志'); $log->err('錯誤日志');
運行腳本:
learnComposer php monolog.php
生成了日志文件monolog.log
[2018-07-12 14:18:14] name.WARNING: 警告日志 [] [] [2018-07-12 14:18:14] name.ERROR: 錯誤日志 [] []
只需一個配置文件composer.json
,一行指令composer install
,代碼中引入autoload.php
,即可完美地使用第三方包。接下來分析composer的包管理規范
composer包管理規范
什么是包?只要存在composer.json
文件的代碼都可以稱之為一個包。
包名稱
包名稱由作者+項目名稱組成。有些包作者名與項目名是相同的,如mustache/mustache
包名稱一定要加上作者,避免沖突。如,同樣的是小龍女這個角色,不同人演繹的效果完全不同。如果你只是說你要看小龍女,可能給你的是一個陳妍希版本的小籠包,而不是你一直仰慕的仙女劉亦菲。
那么,我們怎么根據一個包的項目名去獲取包的信息呢?以mustache
包為例:
- 在packagist查找

點擊進入包信息詳情頁,可以看到包的安裝方法以及版本信息

除了在
composer.json
中寫包的安裝信息,還可以通過composer require mustache/mustache
這種方式直接安裝

- 用
composer search
指令查找

查看包的具體信息 composer show mustache/mustache --all

包版本
在composer.json
中聲明安裝包時,需要指定包的版本,�版本號的指定有多種格式:
- 確定的版本號
格式:1.0.2
最簡單的指定方式,無歧義
- 在一定范圍的版本號
可以定義多個范圍,用逗號隔開,這將被視為一個邏輯AND處理。一個管道符號|將作為邏輯OR處理。 AND 的優先級高於 OR
>=1.0
: 大於或等於1.0版本
>=1.0,<2.0
: 大於或等於1.0,且小於2.0
>=1.0,<1.1|>=1.2
: 大於或等於1.0且等於1.1,或者大於等於1.2
- 通配符
1.0.*
: 只要滿足以1.0開頭的版本號均可
~
下一個重要版本
~1.2 相當於 >=1.2,<2.0
~1.2.3 相當於 >=1.2.3,<1.3
^
大於指定的版本
以下用實例演示版本號的區別:
清空根目錄,composer.json
內容為:
{
"require": {
"mustache/mustache": "2.6.0"
}
}
執行composer install

接下來,刪除vendor
目錄,將版本號改為~2.6.0
, 執行composer install
此時,會發現版本號並沒有變化

這是因為當我們第一次執行composer install
,會生成composer.lock
文件,這個文件記錄了包的指定版本

當我們再次執行composer install
時,�composer會先去composer.lock
中檢查有沒有相應的包信息,如果有,以composer.lock
的版本為准。如果我們要跳過composer.lock
的限制,需要改用composer update
指令

此時,我們看到,版本已經更新為2.6.1
最后再試下將版本號改為^2.6.0
, 執行composer update

此時,已經更新到最新版本號
composer.lock
鎖文件
composer.json
在指定版本時,不一定是精確指定,很多時候是使用范圍指定,只有當我們安裝了包,才知道最終安裝了哪個版本。那么問題來了,如果我們半年后再根據composer.json
來安裝包,可能有些包的版本已經升級了,且向下不兼容,這就有可能導致程序報錯。為避免這種問題,在執行composer install
之后,composer會生成composer.lock
鎖文件。
在鎖文件中可以看到完整的包信息,包括包的版本號。
composer install
命令會先檢查鎖文件是否存在,如果存在,它將下載composer.lock
指定的版本(忽略 composer.json
文件中的定義)
如果在composer.json
中修改了版本號,必須執行composer update
命令,這個命令會根據composer.json
的定義安裝包,並更新composer.lock
文件
鎖文件非常重要!必須將composer.lock
文件上傳到代碼倉庫,這樣才能保證團隊各成員所安裝的包版本是一致的。
創建項目
composer通過create-project
可以直接創建一個完整的項目,將包所在的代碼倉庫clone下來
以創建laravel項目為例:
learnComposer composer create-project laravel/laravel Laravel --prefer-dist "5.5.*"

開發與生產環境分開
有些包我們僅需要在本地安裝,生產環境並不需要,可以在composer.json
中通過require-dev
進行聲明,如:
composer install --no-dev
會忽略require-dev
所聲明的包

composer install
會將require-dev
聲明的包一並獲取

自定義腳本
在Laravel的composer.json
文件中,有這么一段聲明:
"scripts": {
"post-root-package-install": [
"@php -r \"file_exists('.env') || copy('.env.example', '.env');\""
],
"post-create-project-cmd": [
"@php artisan key:generate"
],
"post-autoload-dump": [
"Illuminate\\Foundation\\ComposerScripts::postAutoloadDump",
"@php artisan package:discover"
]
},
表示在執行composer install
時的相應階段,會自動觸發運行腳本

發布自己的包
- github是新建一個倉庫

- 創建
composer.json
文件
在項目根目錄執行composer init
,生成composer.json
配置文件

- 在packagist提交github倉庫地址
在packagist注冊賬號,然后登錄。
提交github倉庫地址

包創建成功

如果用的是國內的鏡像,暫時還不能拉取,需要等國內鏡像同步成功后才能拉取
- 設置自動同步
如果要實現當github倉庫代碼更新就觸發包的自動更新,需要進行以下設置
在github中添加packagist服務

自動同步需要用到packagist的Api token,查看token

提交配置

結語
掌握以上的composer基礎操作,在日常開發中已經足夠使用。如果你是一個沒怎么用過composer的php開發者,強烈推薦你從現在開始就用composer。在我看來,composer不僅僅是一個工具,而是聯結php應用的生態,如果沒有composer或類似的依賴管理工具,很難想象PHP還能保持活力。