本章將解釋包和庫的概念,什么樣的存儲(chǔ)庫是可用的,以及它們?nèi)绾喂ぷ鳌?/p>
在此之前,我們看到存在不同類型的資源庫,我們需要了解一些基本概念,以理解 Composer 是如何構(gòu)建于其上的。
Composer 是一個(gè)依賴管理工具。它在本地安裝一些資源包。一個(gè)包本質(zhì)上就是一個(gè)包含東西的目錄。通常情況下它存儲(chǔ) PHP 代碼,但在理論上它可以是任何東西。并且它包含一個(gè)描述,其中有一個(gè)名稱和一個(gè)版本號(hào),這個(gè)名稱和版本號(hào)用于識(shí)別該包。
事實(shí)上,在 composer 內(nèi)部將每一個(gè)版本都視為一個(gè)單獨(dú)的包。盡管在你使用 composer 時(shí)這種區(qū)別無關(guān)緊要,但當(dāng)你想改變它時(shí),這就顯得至關(guān)重要。
除了名稱和版本號(hào),還存放了有用的元數(shù)據(jù)。與安裝關(guān)系最密切的是 source 信息,它申明了在哪里可以獲得資源包的內(nèi)容。包數(shù)據(jù)指向包內(nèi)容,并有兩種指向方式:dist 和 source。
Dist:?dist 指向一個(gè)存檔,該存檔是對(duì)一個(gè)資源包的某個(gè)版本的數(shù)據(jù)進(jìn)行的打包。通常是已經(jīng)發(fā)行的穩(wěn)定版本。
Source:?source 指向一個(gè)開發(fā)中的源。這通常是一個(gè)源代碼倉庫,例如 git。當(dāng)你想要對(duì)下載下來的資源包進(jìn)行修改時(shí),可以這樣獲取。
你可以使用其中任意一個(gè),或者同時(shí)使用。這取決于其它的一些因素,比如“user-supplied 選項(xiàng)”和“包的穩(wěn)定性”,前者將會(huì)被優(yōu)先考慮。
一個(gè)資源庫是一個(gè)包的來源。它是一個(gè) packages/versions 的列表。Composer 將查看所有你定義的 repositories 以找到你項(xiàng)目需要的資源包。
默認(rèn)情況下已經(jīng)將 Packagist.org 注冊(cè)到 Composer。你可以在?composer.json
?中申明更多的資源庫,把它們加入你的項(xiàng)目中。
資源庫的定義僅可用于“root 包”,而在你依賴的包中定義的資源庫將不會(huì)被加載。如果你想了解其中的原因,請(qǐng)閱讀?FAQ entry。
主資源庫的類型為?composer
。它使用一個(gè)單一的?packages.json
?文件,包含了所有的資源包元數(shù)據(jù)。
這也是 packagist.org 所使用的資源類型。要引用一個(gè)?composer
?資源庫,只需要提供一個(gè)存放?packages.json
?文件的?目錄路徑。比如要引用?packagist.org
?下的?/packages.json
,它的 URL 就應(yīng)該是packagist.org
。而?example.org/packages.json
?的 URL 應(yīng)該是?example.org
。
唯一必須的字段是?packages
。它的 JSON 結(jié)構(gòu)如下:
{
"packages": {
"vendor/package-name": {
"dev-master": { @composer.json },
"1.0.x-dev": { @composer.json },
"0.0.1": { @composer.json },
"1.0.0": { @composer.json }
}
}
}
@composer.json
?標(biāo)記將會(huì)從此包的指定版本中讀取?composer.json
?的內(nèi)容,其內(nèi)至少應(yīng)包含以下信息:
這是一個(gè)最簡單的包定義:
{
"name": "smarty/smarty",
"version": "3.1.7",
"dist": {
"url": "http://www.smarty.net/files/Smarty-3.1.7.zip",
"type": "zip"
}
}
它還可以包含任何在?composer.json 架構(gòu)?中介紹的字段。
notify-batch
?字段允許你指定一個(gè) URL,它將會(huì)在用戶安裝每一個(gè)包時(shí)被調(diào)用。該 URL 可以是(與其資源庫相同域名的)絕對(duì)路徑或者一個(gè)完整的 URL 地址。
例如使用下面的值:
{
"notify-batch": "/downloads/"
}
對(duì)于?example.org/packages.json
?包含的?monolog/monolog
?包,它將會(huì)發(fā)送一個(gè)?POST
?請(qǐng)求到?example.org/downloads/
,使用下面的 JSON request body:
{
"downloads": [
{"name": "monolog/monolog", "version": "1.2.1.0"},
]
}
version
?字段將包含標(biāo)準(zhǔn)化的版本號(hào)。
notify-batch
?字段是可選的。
對(duì)于較大的資源庫,可以拆分?packages.json
?為多個(gè)文件。includes
?字段允許你引用這些額外的文件。
實(shí)例:
{
"includes": {
"packages-2011.json": {
"sha1": "525a85fb37edd1ad71040d429928c2c0edec9d17"
},
"packages-2012-01.json": {
"sha1": "897cde726f8a3918faf27c803b336da223d400dd"
},
"packages-2012-02.json": {
"sha1": "26f911ad717da26bbcac3f8f435280d13917efa5"
}
}
}
文件的 SHA-1 碼允許它被緩存,僅在 hash 值改變時(shí)重新請(qǐng)求。
此字段是可選的。你也許并不需要它來自定義存儲(chǔ)庫。
的對(duì)于非常大的資源庫,像 packagist.org 使用 so-called provider 文件是首選方法。provider-includes
字段允許你設(shè)置一個(gè)列表,來申明這個(gè)資源庫提供的包名稱。在這種情況下文件的哈希算法必須使用 sha256。
providers-url
?描述了如何在服務(wù)器上找到這些 provider 文件。它是以資源庫的根目錄為起點(diǎn)的絕對(duì)路徑。
實(shí)例:
{
"provider-includes": {
"providers-a.json": {
"sha256": "f5b4bc0b354108ef08614e569c1ed01a2782e67641744864a74e788982886f4c"
},
"providers-b.json": {
"sha256": "b38372163fac0573053536f5b8ef11b86f804ea8b016d239e706191203f6efac"
}
},
"providers-url": "/p/%package%$%hash%.json"
}
這些文件包含資源包的名稱以及哈希值,以驗(yàn)證文件的完整性,例如:
{
"providers": {
"acme/foo": {
"sha256": "38968de1305c2e17f4de33aea164515bc787c42c7e2d6e25948539a14268bb82"
},
"acme/bar": {
"sha256": "4dd24c930bd6e1103251306d6336ac813b563a220d9ca14f4743c032fb047233"
}
}
}
上述文件申明了?acme/foo
?和?acme/bar
?可以在這個(gè)資源庫找到,通過加載由?providers-url
?引用的文件,替換?%package%
?為包名并且替換?%hash%
?為 sha256 的值。這些文件本身只包含上文提到的?packages的定義。
這些字段是可選的。你也許并不需要它們來自定義存儲(chǔ)庫。
packages.json
?文件是用一個(gè) PHP 流加載的。你可以使用?options
?參數(shù)來設(shè)定額外的流信息。你可以設(shè)置任何有效的PHP 流上下文選項(xiàng)。更多相關(guān)信息請(qǐng)查看?Context options and parameters。
VCS 表示版本控制系統(tǒng)。這包括像 git、svn 或 hg 這樣的版本管理系統(tǒng)。Composer 有一個(gè)資源類型可以從這些系統(tǒng)安裝軟件包。
這里有幾個(gè)用例。最常見的是維護(hù)自己 fork 的第三方庫。如果你在項(xiàng)目中使用某些庫,并且你決定改變這些庫內(nèi)的某些東西,你會(huì)希望你項(xiàng)目中使用的是你自己的修正版本。如果這個(gè)庫是在 GitHub 上(這種情況經(jīng)常出現(xiàn)),你可以簡單的 fork 它并 push 你的變更到這個(gè) fork 里。在這之后你更新項(xiàng)目的?composer.json
?文件,添加你的 fork 作為一個(gè)資源庫,變更版本約束來指向你的自定義分支。關(guān)于版本約束的命名約定請(qǐng)查看?庫(資源包)。
例如,假設(shè)你 fork 了 monolog,在?bugfix
?分支修復(fù)了一個(gè) bug:
{
"repositories": [
{
"type": "vcs",
"url": "https://github.com/igorw/monolog"
}
],
"require": {
"monolog/monolog": "dev-bugfix"
}
}
當(dāng)你運(yùn)行?php composer.phar update
?時(shí),你應(yīng)該得到你修改的版本,而不是 packagist.org 上的?monolog/monolog
。
注意,你不應(yīng)該對(duì)包進(jìn)行重命名,除非你真的打算擺脫原來的包,并長期的使用你自己的 fork。這樣 Composer 就會(huì)正確獲取你的包了。如果你確定要重命名這個(gè)包,你應(yīng)該在默認(rèn)分支(通常是 master 分支)上操作,而不是特性分支,因?yàn)榘拿秩∽阅J(rèn)分支。
如果其它包依賴你 fork 的這個(gè)分支,可能要對(duì)它做版本號(hào)的行內(nèi)別名設(shè)置,才能夠準(zhǔn)確的識(shí)別版本約束。更多相關(guān)信息請(qǐng)查看?別名。
完全相同的解決方案,也可以讓你使用你 GitHub 和 BitBucket 上的私人代碼庫進(jìn)行工作:
{
"require": {
"vendor/my-private-repo": "dev-master"
},
"repositories": [
{
"type": "vcs",
"url": "git@bitbucket.org:vendor/my-private-repo.git"
}
]
}
唯一的要求是為一個(gè) git 客戶端安裝 SSH 秘鑰。
Git 并不是 VCS 資源庫唯一支持的版本管理系統(tǒng)。
以下幾種都是被支持的:
為了從這些系統(tǒng)獲取資源包,你必須安裝對(duì)應(yīng)的客戶端,這可能是不方便的?;谶@個(gè)原因,這里提供了 GitHub 和 BitBucket 的 API 的特殊支持,以便在無需安裝版本控制系統(tǒng)的情況下獲取資源包。在 VCS 資源庫提供的?dist
?中獲取 zip 存檔。
VCS 驅(qū)動(dòng)將基于 URL 自動(dòng)檢測版本庫類型。但如果可能,你需要明確的指定一個(gè)?git
、svn
?或?hg
?作為資源庫類型,而不是?vcs
。
If you set the?no-api
?key to?true
?on a github repository it will clone the repository as it would with any other git repository instead of using the GitHub API. But unlike using the?git
driver directly, composer will still attempt to use github's zip files.
由于 Subversion 沒有原生的分支和標(biāo)簽的概念,Composer 假設(shè)在默認(rèn)情況下該代碼位于?$url/trunk
、$url/branches
?和?$url/tags
?內(nèi)。如果你的存儲(chǔ)庫使用了不同的布局,你可以更改這些值。例如,如果你使用大寫的名稱,你可以像這樣配置資源庫:
{
"repositories": [
{
"type": "vcs",
"url": "http://svn.example.org/projectA/",
"trunk-path": "Trunk",
"branches-path": "Branches",
"tags-path": "Tags"
}
]
}
如果你的存儲(chǔ)庫目錄中沒有任何分支或標(biāo)簽文件夾,你可以將?branches-path
?或?tags-path
?設(shè)置為?false
。
如果是一個(gè)位于子目錄的包,例如,?/trunk/foo/bar/composer.json
?和?/tags/1.0/foo/bar/composer.json
,那么你可以讓 composer 通過?"package-path"
?選項(xiàng)設(shè)置的子目錄進(jìn)行訪問,在這個(gè)例子中可以將其設(shè)置為?"package-path": "foo/bar/"
。
pear
?類型資源庫,使得從任何 PEAR 渠道安裝資源包成為可能。Composer 將為所有此類型的包增加前綴(類似于?pear-{渠道名稱}/
)以避免沖突。而在之后使用別名時(shí)也增加前綴(如?pear-{渠道別名}/
)。
例如使用?pear2.php.net
:
{
"repositories": [
{
"type": "pear",
"url": "http://pear2.php.net"
}
],
"require": {
"pear-pear2.php.net/PEAR2_Text_Markdown": "*",
"pear-pear2/PEAR2_HTTP_Request": "*"
}
}
在這種情況下渠道的簡稱(別名)是?pear2
,因此?PEAR2_HTTP_Request
?包的名稱應(yīng)該寫作?pear-pear2/PEAR2_HTTP_Request
。
注意:?
pear
?類型的資源庫對(duì)每個(gè) requires 都要做完整的請(qǐng)求,因此可能大大降低安裝速度。
通過自定義供應(yīng)商名稱,對(duì) PEAR 渠道包進(jìn)行別名是允許的。
例:
假設(shè)你有一個(gè)私人 PEAR 庫,并希望使用 Composer 從 VCS 集成依賴。你的 PEAR 庫包含以下資源包:
BasePackage
。IntermediatePackage
?依賴于?BasePackage
。TopLevelPackage1
?和?TopLevelPackage2
?都依賴于?IntermediatePackage
。如果沒有一個(gè)供應(yīng)商別名,Composer 將使用 PEAR 渠道名稱作為包名的一部分:
pear-pear.foobar.repo/BasePackage
pear-pear.foobar.repo/IntermediatePackage
pear-pear.foobar.repo/TopLevelPackage1
pear-pear.foobar.repo/TopLevelPackage2
假設(shè)之后的某個(gè)時(shí)間,你希望將你的 PEAR 包遷移,使用 Composer 資源庫和命名方案,并且采用?foobar
?作為供應(yīng)商名稱。這樣之前使用 PEAR 包的項(xiàng)目將不會(huì)看到更新的資源包,因?yàn)樗鼈冇胁煌墓?yīng)商名稱(foobar/IntermediatePackage
?與?pear-pear.foobar.repo/IntermediatePackage
)。
你可以通過從一開始就為 PEAR 資源庫指定?vendor-alias
?來避免這種情況的發(fā)生,以得到一個(gè)不會(huì)過時(shí)的包名。
為了說明這一點(diǎn),下面的例子會(huì)從你的 PEAR 資源庫中得到?BasePackage
、TopLevelPackage1
?和?TopLevelPackage2
?資源包,并從 Github 資源庫中獲取?IntermediatePackage
?資源包:
{
"repositories": [
{
"type": "git",
"url": "https://github.com/foobar/intermediate.git"
},
{
"type": "pear",
"url": "http://pear.foobar.repo",
"vendor-alias": "foobar"
}
],
"require": {
"foobar/TopLevelPackage1": "*",
"foobar/TopLevelPackage2": "*"
}
}
如果你想使用一個(gè)項(xiàng)目,它無法通過上述任何一種方式支持 composer,你仍然可以使用?package
?類型定義資源庫。
基本上,你可以定義與?packages.json
?中?composer
?類型資源庫相同的信息,但需要為每個(gè)這樣的資源包分別定義。同樣,至少應(yīng)該包含以下信息:name
、version
、(dist
?或?source
)。
這是一個(gè) smarty 模板引擎的例子:
{
"repositories": [
{
"type": "package",
"package": {
"name": "smarty/smarty",
"version": "3.1.7",
"dist": {
"url": "http://www.smarty.net/files/Smarty-3.1.7.zip",
"type": "zip"
},
"source": {
"url": "http://smarty-php.googlecode.com/svn/",
"type": "svn",
"reference": "tags/Smarty_3_1_7/distribution/"
},
"autoload": {
"classmap": ["libs/"]
}
}
}
],
"require": {
"smarty/smarty": "3.1.*"
}
}
通常你不需要去定義?source
,因?yàn)槟悴⒉皇钦娴男枰?/p>
注意:?該資源庫類型存在以下限制,因此應(yīng)盡可能避免使用:
- Composer 將不會(huì)更新資源包,除非你修改了?
version
?字段。- Composer 將不會(huì)更新 commit references,因此如果你使用?
master
?reference,將不得不刪除該程序包以強(qiáng)制更新,并且將不得不面對(duì)一個(gè)不穩(wěn)定的 lock 文件。
盡管大部分的時(shí)間,你大概都會(huì)把資源包放在 packagist.org 上,但這里還將告訴你一些用例,以便你可以自行托管資源庫。
Private company packages:?如果你是一個(gè)公司的職員,對(duì)公司內(nèi)部的資源包使用 composer,你可能會(huì)想讓這些包保持私有的狀態(tài)。
對(duì)于自行托管的軟件包,建議使用?composer
?類型資源庫設(shè)置,它將提供最佳的性能。
這里有一些工具,可以幫助你創(chuàng)建?composer
?類型的資源庫。
packagist 的底層是開源的。這意味著你可以只安裝你自己拷貝的 packagist,改造并使用它。這真的是很直接簡單的事情。然而,由于其規(guī)模和復(fù)雜性,對(duì)于大多數(shù)中小型企業(yè)還是建議使用 Satis。
Packagist 是一個(gè) Symfony2 應(yīng)用程序,并且托管在 GitHub 上?github.com/composer/packagist。它內(nèi)部使用了 composer 并作為 VCS 資源庫與 composer 用戶之間的代理。它擁有所有 VCS 資源包的列表,定期重新抓取它們,并將其作為一個(gè) composer 資源庫。
要設(shè)置你的副本,只需要按照?github.com/composer/packagist?的說明進(jìn)行操作。
Satis 是一個(gè)靜態(tài)的?composer
?資源庫生成器。它像是一個(gè)超輕量級(jí)的、基于靜態(tài)文件的 packagist 版本。
你給它一個(gè)包含?composer.json
?的存儲(chǔ)庫,定義好 VCS 和 資源庫。它會(huì)獲取所有你列出的包,并打印?packages.json
?文件,作為?composer
?類型的資源庫。
更多詳細(xì)信息請(qǐng)查看?github.com/composer/satis?和?Satis article。
在某些情況下,或許沒有能力擁有之前提到的任何一種線上資源庫。Typical example could be cross-organisation library exchange through built artifacts。當(dāng)然大部分的時(shí)間他們都是私有的。為了簡化維護(hù),可以簡單的使用?artifact
?資源庫類型,來引用一個(gè)包含那些私有包的 ZIP 存檔的文件夾:
{
"repositories": [
{
"type": "artifact",
"url": "path/to/directory/with/zips/"
}
],
"require": {
"private-vendor-one/core": "15.6.2",
"private-vendor-two/connectivity": "*",
"acme-corp/parser": "10.3.5"
}
}
每個(gè) zip artifact 都只是一個(gè) ZIP 存檔,放置在?composer.json
?所在的根目錄:
unzip -l acme-corp-parser-10.3.5.zip
composer.json
...
如果有兩個(gè)不同版本的資源包,它們都會(huì)被導(dǎo)入。當(dāng)有一個(gè)新版本的存檔被添加到 artifact 文件夾,并且你運(yùn)行了?update
?命令,該版本就會(huì)被導(dǎo)入,并且 Composer 將更新到最新版本。
你可以在?composer.json
?中禁用默認(rèn)的 Packagist 資源庫。
{
"repositories": [
{
"packagist": false
}
]
}
更多建議: