有使用PHP组件的朋友, 应该会注意到组件里头会有一个文件 composer.json
, 它描述了组件的信息: 名称, 描述, 关键词, 作者, GitHub仓库地址...还有它所依赖的子组件, 是 Composer
工作的核心.
拿一个大家都知道的日志组件 monolog 的 composer.json
为例, 我说下一些比较重要的字段:
{
"name": "monolog/monolog",
"description": "Sends your logs to files, sockets, inboxes, databases and various web services",
"keywords": ["log", "logging", "psr-3"],
"homepage": "http://github.com/Seldaek/monolog",
"type": "library",
"license": "MIT",
"authors": [
{
"name": "Jordi Boggiano",
"email": "j.boggiano@seld.be",
"homepage": "http://seld.be"
}
],
"require": {
"php": "^7.0",
"psr/log": "^1.0.1"
},
"require-dev": {
"phpunit/phpunit": "^5.7",
"graylog2/gelf-php": "^1.4.2",
"sentry/sentry": "^0.13",
"ruflin/elastica": ">=0.90 <3.0",
"doctrine/couchdb": "~1.0@dev",
"aws/aws-sdk-php": "^2.4.9 || ^3.0",
"php-amqplib/php-amqplib": "~2.4",
"swiftmailer/swiftmailer": "^5.3|^6.0",
"php-console/php-console": "^3.1.3",
"jakub-onderka/php-parallel-lint": "^0.9",
"predis/predis": "^1.1",
"phpspec/prophecy": "^1.6.1"
},
"suggest": {
"graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server",
"sentry/sentry": "Allow sending log messages to a Sentry server",
"doctrine/couchdb": "Allow sending log messages to a CouchDB server",
"ruflin/elastica": "Allow sending log messages to an Elastic Search server",
"php-amqplib/php-amqplib": "Allow sending log messages to an AMQP server using php-amqplib",
"ext-amqp": "Allow sending log messages to an AMQP server (1.0 required)",
"ext-mongodb": "Allow sending log messages to a MongoDB server (via driver)",
"mongodb/mongodb": "Allow sending log messages to a MongoDB server (via library)",
"aws/aws-sdk-php": "Allow sending log messages to AWS services like DynamoDB",
"rollbar/rollbar": "Allow sending log messages to Rollbar",
"php-console/php-console": "Allow sending log messages to Google Chrome"
},
"autoload": {
"psr-4": {"Monolog\": "src/Monolog"}
},
"autoload-dev": {
"psr-4": {"Monolog\": "tests/Monolog"}
},
"provide": {
"psr/log-implementation": "1.0.0"
},
"extra": {
"branch-alias": {
"dev-master": "2.0.x-dev"
}
},
"scripts": {
"test": [
"parallel-lint . --exclude vendor",
"phpunit"
]
}
}
安装依赖的时候, 最重要的字段是 name, require 以及 require-dev.
name
该字段标识了组件的名称, 在 所有 的组件中, 它是唯一的;
require
该字段列举出该组件 所需的运行环境 以及 依赖的子组件的版本, 安装该组件时, 会检测运行环境, 并安装该组件的子组件, 以及这些子组件的所有子组件...直到子组件不再依赖任何组件为止;
require-dev
该字段不是必须的, 一般来说不安装里面的依赖, 也是可以用的, 通常都是用来跑单元测试. 依赖的安装同 require
字段.
其他字段对于理解镜像的原理没什么帮助, 有兴趣可以看下 这篇文章.
安装依赖的过程, 其实就是请求服务器, 要求拿到该组件的 composer.json
文件, 然后 JSON
解析, 得到 require
和 require-dev
字段的组件, 一直遍历下去, 根据文件描述的仓库地址 git clone
到本地.
看过我 上一篇文章 的朋友就知道, 文章末尾我们配置了 国内的composer镜像, 用来加速我们安装组件的过程, 它缓存了所有包的 composer.json
, 并把仓库的每一个分支源码, 打包为 zip
压缩包, 并结合 cdn
加速.
镜像服务器提供了让我们得到 composer.json
的接口, 我们只需提交一个包名, 还有请求结果的哈希值(是不是很懵逼, 我怎么知道结果的哈希值), 镜像服务器会返回一个 JSON
, 它包含了很多 composer.json
(至少一个), 这些 composer.json
里面就有我们要找的组件的 composer.json
(根据name字段), 也包括了其他包的, 为什么会带有其他包的呢, 我捣鼓了挺多次, 发现是当 require 字段存在时, 它就顺带返回了, 不过也不是绝对的, 可能考虑体积关系, 也不会返回太多.
说了这么多, 看下 psr/log
组件的请求结果吧, 比较长, 它包含了5个包的信息:
hackification/log
代码语言:txt复制mobio/target
代码语言:txt复制notadd/wechat
代码语言:txt复制psr/log
代码语言:txt复制wedeto/log
代码语言:json复制{
"packages":{
"hackification/log":{
"1.0.2":{
"name":"hackification/log",
"description":"Common interface for logging libraries",
"keywords":[
"log",
"psr",
"psr-3",
"hack",
"hacklang"
],
"homepage":"https://github.com/hackification/log",
"version":"1.0.2",
"version_normalized":"1.0.2.0",
"license":[
"MIT"
],
"authors":[
{
"name":"PHP-FIG",
"homepage":"http://www.php-fig.org/"
}
],
"source":{
"type":"git",
"url":"https://github.com/hackification/log.git",
"reference":"75b02e14bd8e5b8ded75de91d7eb9df6046f7fa7"
},
"dist":{
"type":"zip",
"url":"https://files.phpcomposer.com/files/hackification/log/75b02e14bd8e5b8ded75de91d7eb9df6046f7fa7.zip",
"reference":"75b02e14bd8e5b8ded75de91d7eb9df6046f7fa7",
"shasum":""
},
"type":"library",
"time":"2016-11-08T15:32:34 00:00",
"autoload":{
"psr-4":{
"PsrLog":"Psr/Log/"
}
},
"extra":{
"branch-alias":{
"dev-master":"1.0.x-dev"
}
},
"require":{
"hhvm":">=3.0.0"
},
"replace":{
"psr/log":"*"
},
"uid":1072563
},
"dev-master":{
"name":"hackification/log",
"description":"Common interface for logging libraries",
"keywords":[
"log",
"psr",
"psr-3",
"hack",
"hacklang"
],
"homepage":"https://github.com/hackification/log",
"version":"dev-master",
"version_normalized":"9999999-dev",
"license":[
"MIT"
],
"authors":[
{
"name":"PHP-FIG",
"homepage":"http://www.php-fig.org/"
}
],
"source":{
"type":"git",
"url":"https://github.com/hackification/log.git",
"reference":"75b02e14bd8e5b8ded75de91d7eb9df6046f7fa7"
},
"dist":{
"type":"zip",
"url":"https://files.phpcomposer.com/files/hackification/log/75b02e14bd8e5b8ded75de91d7eb9df6046f7fa7.zip",
"reference":"75b02e14bd8e5b8ded75de91d7eb9df6046f7fa7",
"shasum":""
},
"type":"library",
"time":"2016-11-08T15:32:34 00:00",
"autoload":{
"psr-4":{
"PsrLog":"Psr/Log/"
}
},
"extra":{
"branch-alias":{
"dev-master":"1.0.x-dev"
}
},
"require":{
"hhvm":">=3.0.0"
},
"replace":{
"psr/log":"*"
},
"uid":1072564
}
},
"mobio/target":{
"0.0.5":{
"name":"mobio/target",
"description":"PHP library for myTarget API",
"keywords":[
"php",
"myTarget"
],
"homepage":"",
"version":"0.0.5",
"version_normalized":"0.0.5.0",
"license":[
"MIT"
],
"authors":[
],
"source":{
"type":"git",
"url":"https://github.com/MobioInc/target.git",
"reference":"5baeaae1aa7d85c5b5fd4e33a06608a1de93d73b"
},
"dist":{
"type":"zip",
"url":"https://files.phpcomposer.com/files/MobioInc/target/5baeaae1aa7d85c5b5fd4e33a06608a1de93d73b.zip",
"reference":"5baeaae1aa7d85c5b5fd4e33a06608a1de93d73b",
"shasum":""
},
"type":"library",
"time":"2016-10-31T08:52:52 00:00",
"autoload":{
"psr-4":{
"MobioTarget":"src/"
}
},
"require":{
"php":">=5.5.0",
"psr/log":"~1.0",
"guzzlehttp/guzzle":"^6.1"
},
"require-dev":{
"phpunit/phpunit":"^5.5"
},
"provide":{
"psr/log":"1.0.0"
},
"uid":1060012
},
"dev-master":{
"name":"mobio/target",
"description":"PHP library for myTarget API",
"keywords":[
"php",
"myTarget"
],
"homepage":"",
"version":"dev-master",
"version_normalized":"9999999-dev",
"license":[
"MIT"
],
"authors":[
],
"source":{
"type":"git",
"url":"https://github.com/MobioInc/target.git",
"reference":"70aa382ca6d3ba3b5a834bbe85d3fc2cbfec965f"
},
"dist":{
"type":"zip",
"url":"https://files.phpcomposer.com/files/MobioInc/target/70aa382ca6d3ba3b5a834bbe85d3fc2cbfec965f.zip",
"reference":"70aa382ca6d3ba3b5a834bbe85d3fc2cbfec965f",
"shasum":""
},
"type":"library",
"time":"2017-02-13T18:53:10 00:00",
"autoload":{
"psr-4":{
"MobioTarget":"src/"
}
},
"require":{
"php":">=5.5.0",
"guzzlehttp/guzzle":"^6.1",
"psr/log":"~1.0"
},
"require-dev":{
"phpunit/phpunit":"^5.5"
},
"provide":{
"psr/log":"1.0.0"
},
"uid":700331
}
},
"notadd/wechat":{
"dev-master":{
"name":"notadd/wechat",
"description":"Notadd's Wechat Module.",
"keywords":[
"framework",
"cms",
"member",
"notadd"
],
"homepage":"https://notadd.com",
"version":"dev-master",
"version_normalized":"9999999-dev",
"license":[
"Apache-2.0"
],
"authors":[
{
"name":"Notadd",
"email":"notadd@ibenchu.com"
}
],
"source":{
"type":"git",
"url":"https://github.com/notadd/wechat.git",
"reference":"e3f684cd225f3fadf21953c0289cb8426baad0e5"
},
"dist":{
"type":"zip",
"url":"https://files.phpcomposer.com/files/notadd/wechat/e3f684cd225f3fadf21953c0289cb8426baad0e5.zip",
"reference":"e3f684cd225f3fadf21953c0289cb8426baad0e5",
"shasum":""
},
"type":"notadd-module",
"time":"2017-11-13T04:23:05 00:00",
"autoload":{
"psr-4":{
"NotaddWechat":"src/"
}
},
"require":{
"php":">=7.0",
"overtrue/wechat":"~3.1"
},
"require-dev":{
"notadd/installers":"0.14.*",
"notadd/testing":"0.4.*",
"phpunit/phpunit":"~6.0"
},
"replace":{
"guzzlehttp/guzzle":"*",
"guzzlehttp/promises":"*",
"guzzlehttp/psr7":"*",
"monolog/monolog":"*",
"psr/container":"*",
"psr/http-message":"*",
"psr/log":"*",
"symfony/http-foundation":"*",
"symfony/polyfill-mbstring":"*",
"symfony/psr-http-message-bridge":"*"
},
"uid":1108963
}
},
"psr/log":{
"1.0.0":{
"name":"psr/log",
"description":"Common interface for logging libraries",
"keywords":[
"log",
"psr",
"psr-3"
],
"homepage":"",
"version":"1.0.0",
"version_normalized":"1.0.0.0",
"license":[
"MIT"
],
"authors":[
{
"name":"PHP-FIG",
"homepage":"http://www.php-fig.org/"
}
],
"source":{
"type":"git",
"url":"https://github.com/php-fig/log.git",
"reference":"fe0936ee26643249e916849d48e3a51d5f5e278b"
},
"dist":{
"type":"zip",
"url":"https://files.phpcomposer.com/files/php-fig/log/fe0936ee26643249e916849d48e3a51d5f5e278b.zip",
"reference":"fe0936ee26643249e916849d48e3a51d5f5e278b",
"shasum":""
},
"type":"library",
"time":"2012-12-21T11:40:51 00:00",
"autoload":{
"psr-0":{
"PsrLog":""
}
},
"uid":29358
},
"1.0.1":{
"name":"psr/log",
"description":"Common interface for logging libraries",
"keywords":[
"log",
"psr",
"psr-3"
],
"homepage":"https://github.com/php-fig/log",
"version":"1.0.1",
"version_normalized":"1.0.1.0",
"license":[
"MIT"
],
"authors":[
{
"name":"PHP-FIG",
"homepage":"http://www.php-fig.org/"
}
],
"source":{
"type":"git",
"url":"https://github.com/php-fig/log.git",
"reference":"5277094ed527a1c4477177d102fe4c53551953e0"
},
"dist":{
"type":"zip",
"url":"https://files.phpcomposer.com/files/php-fig/log/5277094ed527a1c4477177d102fe4c53551953e0.zip",
"reference":"5277094ed527a1c4477177d102fe4c53551953e0",
"shasum":""
},
"type":"library",
"time":"2016-09-19T16:02:08 00:00",
"autoload":{
"psr-4":{
"PsrLog":"Psr/Log/"
}
},
"extra":{
"branch-alias":{
"dev-master":"1.0.x-dev"
}
},
"require":{
"php":">=5.3.0"
},
"uid":1000789
},
"1.0.2":{
"name":"psr/log",
"description":"Common interface for logging libraries",
"keywords":[
"log",
"psr",
"psr-3"
],
"homepage":"https://github.com/php-fig/log",
"version":"1.0.2",
"version_normalized":"1.0.2.0",
"license":[
"MIT"
],
"authors":[
{
"name":"PHP-FIG",
"homepage":"http://www.php-fig.org/"
}
],
"source":{
"type":"git",
"url":"https://github.com/php-fig/log.git",
"reference":"4ebe3a8bf773a19edfe0a84b6585ba3d401b724d"
},
"dist":{
"type":"zip",
"url":"https://files.phpcomposer.com/files/php-fig/log/4ebe3a8bf773a19edfe0a84b6585ba3d401b724d.zip",
"reference":"4ebe3a8bf773a19edfe0a84b6585ba3d401b724d",
"shasum":""
},
"type":"library",
"time":"2016-10-10T12:19:37 00:00",
"autoload":{
"psr-4":{
"PsrLog":"Psr/Log/"
}
},
"extra":{
"branch-alias":{
"dev-master":"1.0.x-dev"
}
},
"require":{
"php":">=5.3.0"
},
"uid":1029935
},
"dev-master":{
"name":"psr/log",
"description":"Common interface for logging libraries",
"keywords":[
"log",
"psr",
"psr-3"
],
"homepage":"https://github.com/php-fig/log",
"version":"dev-master",
"version_normalized":"9999999-dev",
"license":[
"MIT"
],
"authors":[
{
"name":"PHP-FIG",
"homepage":"http://www.php-fig.org/"
}
],
"source":{
"type":"git",
"url":"https://github.com/php-fig/log.git",
"reference":"4ebe3a8bf773a19edfe0a84b6585ba3d401b724d"
},
"dist":{
"type":"zip",
"url":"https://files.phpcomposer.com/files/php-fig/log/4ebe3a8bf773a19edfe0a84b6585ba3d401b724d.zip",
"reference":"4ebe3a8bf773a19edfe0a84b6585ba3d401b724d",
"shasum":""
},
"type":"library",
"time":"2016-10-10T12:19:37 00:00",
"autoload":{
"psr-4":{
"PsrLog":"Psr/Log/"
}
},
"extra":{
"branch-alias":{
"dev-master":"1.0.x-dev"
}
},
"require":{
"php":">=5.3.0"
},
"uid":29285
}
},
"wedeto/log":{
"v0.9.1":{
"name":"wedeto/log",
"description":"Wedeto Platform - Logger",
"keywords":[
],
"homepage":"https://wedeto.net/",
"version":"v0.9.1",
"version_normalized":"0.9.1.0",
"license":[
"MIT"
],
"authors":[
{
"name":"Egbert van der Wal",
"email":"ewal@pointpro.nl"
}
],
"source":{
"type":"git",
"url":"https://github.com/Wedeto/Log.git",
"reference":"acc7f4aa66965dd2627a3886c9ac8b0d77b0a268"
},
"dist":{
"type":"zip",
"url":"https://files.phpcomposer.com/files/Wedeto/Log/acc7f4aa66965dd2627a3886c9ac8b0d77b0a268.zip",
"reference":"acc7f4aa66965dd2627a3886c9ac8b0d77b0a268",
"shasum":""
},
"type":"library",
"time":"2017-04-10T12:31:55 00:00",
"autoload":{
"psr-4":{
"WedetoLog":"src/"
}
},
"require":{
"psr/log":"1.0.*",
"wedeto/util":"0.9.*",
"php":">=7.0.0"
},
"require-dev":{
"mikey179/vfsstream":"~1"
},
"provide":{
"psr/log":"1.0.*"
},
"uid":1336127
},
"v0.9.2":{
"name":"wedeto/log",
"description":"Wedeto Platform - Logger",
"keywords":[
],
"homepage":"https://wedeto.net/",
"version":"v0.9.2",
"version_normalized":"0.9.2.0",
"license":[
"MIT"
],
"authors":[
{
"name":"Egbert van der Wal",
"email":"ewal@pointpro.nl"
}
],
"source":{
"type":"git",
"url":"https://github.com/Wedeto/Log.git",
"reference":"55e6b03f0b446b7054078fd8a680ad1499d26264"
},
"dist":{
"type":"zip",
"url":"https://files.phpcomposer.com/files/Wedeto/Log/55e6b03f0b446b7054078fd8a680ad1499d26264.zip",
"reference":"55e6b03f0b446b7054078fd8a680ad1499d26264",
"shasum":""
},
"type":"library",
"time":"2017-04-10T18:15:36 00:00",
"autoload":{
"psr-4":{
"WedetoLog":"src/"
}
},
"require":{
"psr/log":"1.0.*",
"wedeto/util":"0.9.*",
"php":">=7.0.0"
},
"require-dev":{
"mikey179/vfsstream":"~1"
},
"provide":{
"psr/log":"1.0.*"
},
"uid":1336697
}
}
}
}
可以看到, packages
字段里面有5个包, 里面的 psr/log
字段就是我们要找的, 而里面有各个分支的 composer.json
, 以分支 1.0.0
为例, 里面有两个很关键的字段, source 和 dist:
{
"source":{
"type":"git",
"url":"https://github.com/php-fig/log.git",
"reference":"fe0936ee26643249e916849d48e3a51d5f5e278b"
},
"dist":{
"type":"zip",
"url":"https://files.phpcomposer.com/files/php-fig/log/fe0936ee26643249e916849d48e3a51d5f5e278b.zip",
"reference":"fe0936ee26643249e916849d48e3a51d5f5e278b",
"shasum":""
}
}
dist
该字段其实就是加速的 zip
压缩包, 无需 git clone
, 只需把 zip
下载到本地, 解压完, 分支 1.0.0
就装好了.
source
这个字段的作用, 就是万一 dist
字段的 zip
下载不了, 不会马上中断整个安装流程, 而是接着 git clone
. 也就是说, dist
字段失败, 或者压根就没有 dist
字段, 就走 source
字段.
<hr>
看到这里, 对 Composer
的了解应该多了很多吧? 还记得 请求结果的哈希值 吗? 这个哈希哪里来的, 为什么我可以提前知道这个请求的 JSON
的哈希值? 还有, 接口在哪里? 镜像服务器的官方网站, 并没有提供啊...