2.5. composer.json 完全解析
composer.json 组织架构
这个章节将会讲解 composer.json
中所有字段。
JSON 格式
使用 JSON schema 模式来记录和验证格式,你也可以在 getcomposer.org/schema.json 中来参照。
根项目
根项目是由当前项目目录下的 composer.json
定义的项目,composer.json
中定义了您当前项目的依赖项。
某些字段仅在根项目中的上下文中应用,举个例子, config
字段,只有根项目才能定义和配置,依赖项的配置将会被忽略,这代表 config
字段是 root-only
注意:当前项目可以是根项目,也可以不是,具体取决于你的上下文环境,例如,如果您的项目依赖于
monolog
库,那么您的项目就是根节点。但是,如果您从 GitHub 中克隆monolog
库来修复它的 bug,那么monolog
库就是根项目。
属性
name
名称
包的名称,由作者名称和项目名称组成,使用 /
分割,例如:
- monolog/monolog
- igorw/event-source
包名称可以包含任何字符,包括空格,并且不区分大小写 ( foo/bar
和 Foo/Bar
会被认为是同一个包)。为了简化安装,建议定义一个不包含非字母数字字符或空格的短名称。
发布一个包(库)的必要条件
description
描述
包的简短描述,通常这是一行介绍就行。
发布一个包(库)的必要条件
version
版本
包的版本,在大多数情况下,这不是必须的,应该省略(参考下文)。
必须遵循 X.Y.Z
或 vX.Y.Z
,可选后缀 -dev
, -patch
( -p
), -alpha
( -a
), -beta
( -b
) 或 -RC
, patch
, alpha
, beta
和 RC
后缀也可以跟一个数字。
例如:
- 1.0.0
- 1.0.2
- 1.1.0
- 0.2.5
- 1.0.0-dev
- 1.0.0-alpha3
- 1.0.0-beta2
- 1.0.0-RC5
- v2.0.4-p1
如果包仓库可以从某个位置推断出版本,则可填,例如 VCS 仓库中的 VCS 标记名称,这种情况还是建议省略掉。
注意: 包列表使用 VCS 存储,因此上面的语句对于包列表也是有效。由于人为错误,您自己指定版本很有可能最终会在某些时候出现问题(建议搜索学习:语义化版本)。
type
类型
包的类型,默认为库 library
。
包类型用于自定义安装逻辑。如果您有一个包需要一个特殊逻辑,您可以定义一个自定义类型。 这可以是 symfony-bundle
, wordpress-plugin
或者 typo3-module
。这些类型都将用于某些特定的项目。而对应的项目将要提供一种能够安装该类型包的安装程序。
Composer
原生支持以下4种类型:
- library: 默认类型,它只需要将文件复制到
vendor
目录。 - project: 当前包是一个项目,而不是一个库。例:框架应用程序 Symfony standard edition,内容管理系统 SilverStripe installer 或者完全成熟的分布式应用程序。使用 IDE 创建一个新的工作区时,这可以为其提供项目列表的初始化。
- metapackage: 包含需求并将触发其安装的空包,但不包含文件,并且不会向系统写入任何内容。因此这种安装类型并不需要一个 dist 或 source。
- composer-plugin: 一个安装类型为
composer-plugin
的包,它有一个自定义安装类型,可以为其它包提供一个installler
。详细请查看自定义安装类型。
只有在安装过程中需要自定义逻辑时才使用自定义类型。建议省略该字段并将其默认为库 library
。
keywords
一组用于搜索与筛选的与包相关的关键字。
例如:
- logging
- events
- database
- redis
- templating
非必须。
homepage
项目网站的 URL 地址。
非必须。
readme
README 文档的绝对路径。
非必须。
time
版本发布日期。
必须是 YYYY-MM-DD
或者 YYYY-MM-DD HH:MM:SS
格式。
非必须。
license
包的许可证。可以是一个字符串或者是一个字符串数组。
最常见的许可证推荐表示法如下(按字母排序):
- Apache-2.0
- BSD-2-Clause
- BSD-3-Clause
- BSD-4-Clause
- GPL-2.0-only / GPL-2.0-or-later
- GPL-3.0-only / GPL-3.0-or-later
- LGPL-2.1-only / LGPL-2.1-or-later
- LGPL-3.0-only / LGPL-3.0-or-later
- MIT
虽然是一个可选项,但是非常建议提供此项信息。更多的标识符列在了 SPDX Open Source License Registry。
对于闭源软件,你可能需要使用 "proprietary"
作为许可标识符。
示例:
{
"license": "MIT"
}
对于一个包来说,当在多个许可证之间进行选择时(『析取许可证』),可以将多个许可指定为一个数组。
一个析取许可证的示例:
{
"license": [
"LGPL-2.1-only",
"GPL-3.0-or-later"
]
}
也可以在括号内用 "or" 将它们分开。
{
"license": "(LGPL-2.1-only or GPL-3.0-or-later)"
}
同理,当需要使用多个许可证时(『合取许可证』),它们应该在括号内使用 "and" 分隔。
authors
包的作者。这是一个对象数组。
每一个作者对象可以包含以下属性:
- name: 作者的名字。通常是真实姓名。
- email: 作者的邮件地址。
- homepage: 作者个人网站的 URL 地址。
- role: 作者在项目中担任的角色(如:开发者或者译者)。
示例:
{
"authors": [
{
"name": "Nils Adermann",
"email": "naderman@naderman.de",
"homepage": "http://www.naderman.de",
"role": "Developer"
},
{
"name": "Jordi Boggiano",
"email": "j.boggiano@seld.be",
"homepage": "https://seld.be",
"role": "Developer"
}
]
}
虽然是可选项,但是强烈建议写上。
support
获取对项目支持的信息对象。
对象信息必须包括以下属性:
- email: 项目支持 email 地址。
- issues: 跟踪问题的 URL 地址。
- forum: 论坛 URL 地址。
- wiki: Wiki URL 地址。
- irc: IRC 聊天频道地址,as irc://server/channel.
- source: 网址浏览或下载源。
- docs: 文件的 URL 。
- rss: RSS 源的 URL 。
一个实例:
{
"support": {
"email": "support@example.org",
"irc": "irc://irc.freenode.org/composer"
}
}
可选。
包链接
所有这些都使用一个对象,该对象通过版本限制将包名称映射到包的版本。在这里阅读更多关于版本的信息。
实例:
{
"require": {
"monolog/monolog": "1.0.*"
}
}
所有的这些都是可选的。
require
和 require-dev
还支持稳定性标签 (root-only)。 这允许你在 minimum-stability 设定的范围外做进一步的限制或扩展。 您可以将它们应用于版本约束,或者将它们应用到空版本约束,例如,如果允许不稳定的依赖性包。
实例:
{
"require": {
"monolog/monolog": "1.0.*@beta",
"acme/foo": "@dev"
}
}
如果一个依赖有对另一个不稳定包的依赖, 你最好在 require
中显示的定义它,并带上详细的稳定性标识。
实例:
如果 doctrine/doctrine-fixtures-bundle
需要 "doctrine/data-fixtures": "dev-master"
然后在根 Composer.json 中你需要添加下面的第二行,以允许 dev
发布 doctrine/data-fixtures
包:
{
"require": {
"doctrine/doctrine-fixtures-bundle": "dev-master",
"doctrine/data-fixtures": "@dev"
}
}
require
和 require-dev
还支持对 dev(开发)版本的明确引用(即:版本控制中的提交编号 commit),以确保它们被锁定到一个给定的状态,即使你运行了更新命令。你只需要明确一个开发版本号,并带上诸如 #<ref>
的标识。这也是一个 root-only 特性,将在依赖关系中被忽略。
例如:
{
"require": {
"monolog/monolog": "dev-master#2eb0c0978d290a1c45346a1955188929cb4e5db7",
"acme/foo": "1.0.x-dev#abc123"
}
}
请注意:这个特性有严重的技术限制,即 composer.json 的元数据仍将被从你在哈希前面指定的分支中读取。因此,此功能应该被用于开发期间临时修复问题时使用,然后之后你就可以切换至打过 tag 过的发行版本。Composer 团队对此功能不提供活跃的支持,也不接受由此产生的 BUG 报告。
您也可以使用 “版本行内别名”(inline-alias)包约束,用以满足其它情况下满足不了的限定。了解更多信息 查阅别名相关文章。
require
和 require-dev
同时也支持指定你项目成功运行所需要的 PHP 版本和 PHP 扩展。
例如:
{
"require" : {
"php" : "^5.5 || ^7.0",
"ext-mbstring": "*"
}
}
请注意:项目中列举出 PHP 扩展其实是挺重要的。并非所有的 PHP 安装后的环境都是相同的:有些可能缺失了部分扩展而你却认为是标准化安装的(例如
ext-mysqli
在 Fedora/CentOS 精简化安装中就不会被默认安装的)。一例失败的 PHP 扩展依赖列举会带来糟糕的使用体验:Composer 安装你包的时候不报错,但运行时却失败。这个composer show --platform
命令可用于列出你系统中可用的 PHP 扩展,可用来帮助你列举你用到的和所需的扩展。除此之外,你也可以使用第三方的工具来分析你项目用到的扩展的清单。
require
必须安装的依赖包列表,这些包必须满足条件,否则不会安装。
require-dev (root-only)
开发或运行测试时的依赖包列表。根目录下的 composer.json
即 root 包,root 包需要的 dev
依赖默认安装, 安装和更新都支持 —no-dev 选项,以避免 dev
依赖被安装。
conflict
列表中的包与当前包冲突,不允许同时安装。
请注意,在
conflict
中,比如指定<1.0 >=1.1
的版本范围时,表示小于1.0
且大于或等于1.1
的版本冲突,这种约束写法是错误的,应为<1.0 | >= 1.1
。
replace
列表中的包将被当前包替换。所以你可以 fork 一个包,以不同的名称、版本号发布。之后如果有其他任何包依赖原包,将依赖于你 fork 的包。
这对于一个内部包含子包的主包很有用。例如 symfony/symfony
这个主包,包含了 Symfony
的所有组件,而这些组件又可以单独的发布。如果你 require 了主包,那么它就会自动完成其下各个子包的依赖,因为主包取代了子包。
请注意,在上述方法取代子包时,你应该只对子包使用
self.version
这一个版本约束,以确保主包仅替换子包的准确版本,而不是其他版本。
provider
此程序包提供了一个其他程序包列表。 这对于通用接口非常有用, 一个包可能依赖于一些虚拟的logger
包,任何实现这个logger接口的库都可以在provide
中列出来。
suggest
建议的包可以增强或者适用于当前的包,这些信息,在这个包安装完成之后显示,以便给用户提供可供安装的更多包的信息,即使他们不是被严格要求的。
格式如同上面包的链接,除了值是纯文本,且不包含版本信息。
例子如下:
{
"suggest": {
"monolog/monolog": "Allows more advanced logging of the application flow",
"ext-xml": "Needed to support XML format in class Foo"
}
}
autoload
PHP 自动加载的映射。
支持 PSR-4
和 PSR-0
自动加载,class
映射 和 files
引用。
推荐使用 PSR-4
规范(添加类时,无需重新生成自动加载映射)。
PSR-4
使用 PSR-4
时,你可以定义从命名空间到路径的映射。
例如,当加载 Foo\\Bar\\Baz
这样的类,且在 composer.json
定义命名空间前缀 Foo\\
指向目录 src/
时 ,自动加载器将查找 src/Bar/Baz.php
且命名空间前缀为 Foo\\
的文件并包含它(如果存在)。
请注意,与旧的
PSR-0
不同的是,PSR-4
的文件路径中不存在与前缀Foo\\
对应的Foo/
目录。
命名空间前缀必须以 \\
结尾,以避免类似前缀间的冲突。例如,前缀 Foo
可能匹配 ForBar
命名空间的类,因此尾部的反斜杠解决了这种问题。
在安装、更新时,PSR-4的引用都被生成单个 key=>value
的数组,该数组可以在生成文件 vendor/composer/autoload_psr4.php
中查看。
例:
{
"autoload": {
"psr-4": {
"Monolog\\": "src/",
"Vendor\\Namespace\\": ""
}
}
}
如果需要在多个目录中加载相同前缀,可以指定为数组。
{
"autoload": {
"psr-4": { "Monolog\\": ["src/", "lib/"] }
}
}
如果需要加载目录中所有命名空间的类,可以使用一个空前缀,如:
{
"autoload": {
"psr-4": { "": "src/" }
}
}
PSR-0
使用 PSR-0
时,可以定义相对于包的根目录,命名空间到路径的映射。也支持 PEAR-style
的非命名空间约定。
请注意,
PSR-0
的命名空间前缀也必须以\\
结尾,以避免类似前缀间的冲突。
在安装、更新时,PSR-0
的引用都被生成单个 key=>value
的数组,该数组可以在生成文件 vendor/composer/autoload_namespaces.php
中查看。
例:
{
"autoload": {
"psr-0": {
"Monolog\\": "src/",
"Vendor\\Namespace\\": "src/",
"Vendor_Namespace_": "src/"
}
}
}
如果需要在多个目录中加载相同前缀,可以指定为数组:
{
"autoload": {
"psr-0": { "Monolog\\": ["src/", "lib/"] }
}
}
PSR-0
不仅可以用于命名空间的声明,还可以直接指定到类。这对于在全局命名空间中只有一个类的包非常有用。例如,只有一个 php
文件位于包的根目录中,则可能声明为:
{
"autoload": {
"psr-0": { "UniqueGlobalClass": "" }
}
}
如果需要加载目录中所有命名空间的类,可以使用一个空前缀,如:
{
"autoload": {
"psr-0": { "": "src/" }
}
}
Classmap
在安装或更新的时候,classmap
被组合成单个键值对数组(key=>value)的形式,这个数组可以在 vendor/composer/autoload_classmap.php
中找到。这个映射是通过扫描给定的 文件夹/文件中所有的.php
和.inc
来生成的。
您可以通过生成类映射来自动加载不遵循PSR-0/4的库。通过设定要搜索类的所有目录或文件来进行配置。
Example:
{
"autoload": {
"classmap": ["src/", "lib/", "Something.php"]
}
}
Files
如果你想在每个请求中引入某个文件,那么你可以使用 files
自动加载机制。这有利于加载包中无法自动加载的php函数。
Example:
{
"autoload": {
"files": ["src/MyLibrary/functions.php"]
}
}
Exclude files from classmaps
我们可以使用 exclude-from-classmap
从类库映射中排查某些文件或文件夹。这很方便我们在生成环境中排查测试类,例如,在构建加载的时候自动加载器会排除这些类。
类映射生成器将忽略此处配置的路径中的所有文件。这些路径是包根目录(即composer.json位置)的绝对路径,并且支持*
来匹配除斜杠之外的任何东西,并且**
来匹配任何东西。 **
隐含地添加到路径的末尾。
Example:
{
"autoload": {
"exclude-from-classmap": ["/Tests/", "/test/", "/tests/"]
}
}
优化自动加载
自动加载会对请求时间产生较大的影响(类较多的大型框架中每个请求自动加载器将会耗时 50-100 ms)。点击查看如何 优化自动加载。
autoload-dev (root-only)
这个节点允许允许为开发阶段自定义加载规则。
运行测试套件所需的类不应包含在主自动加载规则中,以避免在生产中污染自动加载器以及其他人将您的包用作依赖项。
因此,最好使用专用路径进行单元测试,并将其添加到 autoload-dev 部分。
例如:
{
"autoload": {
"psr-4": { "MyLibrary\\": "src/" }
},
"autoload-dev": {
"psr-4": { "MyLibrary\\Tests\\": "tests/" }
}
}
include-path
弃用:
这里仅仅用于支持遗留项目,所有的新代码最好使用自动加载。因此,这是一种弃用的做法,但该功能本身不会从 Composer 中消失。
应该附加到PHP的 include_path
的路径列表。
例如:
{
"include-path": ["lib/"]
}
这是可选的。
target-dir
弃用:这仅用于支持传统的 PSR-0 样式自动加载,并且所有新代码最好是没有使用 target-dir 的 PSR-4,鼓励使用 PHP 命名空间的 PSR-0 项目转移到PSR-4。
定义安装目标。
如果包的根路径位于命名空间声明之下,则无法正确自动加载。 target-dir
解决了这个问题。
例如 Symfony,组件都是单独的包。 Yaml 组件位于 Symfony\Component\Yaml
下。包的根路径是 Yaml
目录。如果要自动加载,我们需要确保它没有安装到 vendor/symfony/ yaml
中,而是安装到 vendor/symfony/yaml/Symfony/Component/Yaml
中,以便自动加载器可以从 vendor/symfony/yaml
中加载。
为此,autoload
和 target-dir
定义如下:
{
"autoload": {
"psr-0": { "Symfony\\Component\\Yaml\\": "" }
},
"target-dir": "Symfony/Component/Yaml"
}
这是可选的。
minimum-stability (root-only)
这定义了按稳定性过滤包的默认值,默认为stable
。所以如果你依赖dev
包,你应该在你的文件中指定。
所有包都将根据稳定性检出相应的版本,那些低于 minimum-stability
设置的版本将被自动忽略。(请注意,你还可以使用在 require
中指定的版本约束来定义每个包的稳定性要求(请参阅package links)。
可用选项(按稳定性排序)是 dev
,alpha
,beta
,RC
和 stable
。
prefer-stable (root-only)
启用此项后,如果可以找到兼容的稳定包,Composer 将优先选择比不稳定包更稳定的包。如果您需要开发版本或者某个软件包只有alpha可用,那么仍然会选择那些允许最小稳定性允许的包。
使用 "prefer-stable": true
来开启此项.
repositories (root-only)
使用自定义的安装源。
Composer 默认只使用 packagist 的安装源。通过定义 repositories 你可以从任何其他地方获取包。
存储库不会递归解析,您只能将它们添加到主 composer.json
中。依赖项中 composer.json
的 repositories 配置被忽略。
支持以下安装源类型:
- composer: Composer 存储库只是通过网络(HTTP,FTP,SSH)提供的
packages.json
文件,其中包含带有额外dist
或source
信息的composer.json
对象列表。packages.json
文件使用PHP流加载。您可以使用options
参数在该流上设置额外选项。 - vcs: 版本控制系统存储库可以从git, svn, fossil 或 hg repositories。
- pear: 通过 pear,可以将任何 pear 存储库导入 Composer 项目。
- package:
如果依赖于一个不支持 composer 的项目,可以使用package
来定义包。只需要内联composer.json
对象。
更多信息,请参阅 Repositories.
例如:
{
"repositories": [
{
"type": "composer",
"url": "http://packages.example.com"
},
{
"type": "composer",
"url": "https://packages.example.com",
"options": {
"ssl": {
"verify_peer": "true"
}
}
},
{
"type": "vcs",
"url": "https://github.com/Seldaek/monolog"
},
{
"type": "pear",
"url": "https://pear2.php.net"
},
{
"type": "package",
"package": {
"name": "smarty/smarty",
"version": "3.1.7",
"dist": {
"url": "https://www.smarty.net/files/Smarty-3.1.7.zip",
"type": "zip"
},
"source": {
"url": "https://smarty-php.googlecode.com/svn/",
"type": "svn",
"reference": "tags/Smarty_3_1_7/distribution/"
}
}
}
]
}
注意:顺序在这里很重要。在查找包时,Composer 将从第一个存储库查找到最后一个存储库,然后选择第一个匹配项。默认情况下,最后添加 Packagist ,这意味着自定义存储库可以覆盖它的包。
也可以使用JSON对象表示法。但是 JSON 的 key/value 是无序的,因此无法保证一致的行为。
{
"repositories": {
"foo": {
"type": "composer",
"url": "http://packages.foo.com"
}
}
}
config (root-only)
一组配置选项。它仅用于项目。详情请参阅 Config 。
scripts (root-only)
Composer 允许再安装过程的各个部分中执行脚本。
详情请参阅 Scripts 。
extra
scripts
使用的任意扩展数据。
这几乎可以是任意的东西,要从脚本事件处理程序中访问它,您可以执行以下操作:
$extra = $event->getComposer()->getPackage()->getExtra();
这是可选的。
bin
一组被链接到 bin-dir
的二进制文件(来自config)。
详情请参阅 Vendor Binaries 。
这是可选的。
archive
一组用于创建包归档的选项。
支持以下选项:
- exclude:允许配置一组需要排除的路径,语法与
.gitignore
文件一致。如果开头使用(!)将代表包含任意匹配文件,即使它们之前被排除了。/
表示从项目相对路径的根目录进行匹配,*
不会扩展到目录分隔符。
例如:
{
"archive": {
"exclude": ["/foo/bar", "baz", "/*.test", "!/foo/bar/baz"]
}
}
这个例子将会包含 /dir/foo/bar/file
, /foo/bar/baz
, /file.php
, /foo/my.test
并且排除 /foo/bar/any
, /foo/baz
, 和 /my.test
.
这是可选的。
abandoned(弃用)
标记此包是否已经被弃用
它可以是布尔值也可以指向推荐替代的包名称或 URL。
例如:
使用 "abandoned": true
来定义这个包已经被弃用了。
使用 "abandoned": "monolog/monolog"
来定义这个包已经被弃用,并且它的替代包是 monolog/monolog
。
默认为 false。
这是可选的。
non-feature-branches(非功能分支)
一组非数字(例如 “latest” 或其他类似的标记)命名的分支的正则表达式列表,不会作为功能分支处理。这是一个字符串数组。
如果您有非数字分支名称,例如 "latest", "current", "latest-stable" 或其它类似的命名,它们看起来不像版本号,那么 Composer 会将此类分支作为功能分支处理。它会搜索父分支,直到搜索到版本或在特殊分支(如 master)结束,包的根版本号成为父分支的版本或至少是master或者其他类似的命名。
要将非数字命名分支作为版本处理,而不是搜索具有有效版本或特殊分支名称(如 master )的父分支,可以设置分支名称的模式,这些模式应作为 dev 版本分支处理。
这将有利于依赖使用 “self.version” 的包,因此不是dev-master,而是安装了相同的分支(例如:latest-testing)。
例如:
如果你有一个测试分支,在测试阶段大量维护并部署到你的临时环境,通常 composer show -s
会给你 versions : * dev-master
。
如果你将 latest-.*
配置为非功能分支的模式,如下所示:
{
"non-feature-branches": ["latest-.*"]
}
那么 composer show -s
将会给你 versions : * dev-latest-testing
.
这是可选的。
本译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。
推荐文章: