阅读说明
软件版本
- PHP v8.2.8
- Composer v2.7.7
问题过程
背景
最近在给Laravel v11.1.4安装依赖的时候遇到如下报错:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
|
Downloading https://mirrors.aliyun.com/composer/p2/fruitcake/php-cors~dev.json if modified
[304] https://mirrors.aliyun.com/composer/p2/fruitcake/php-cors~dev.json
Reading /Users/jayce/Library/Caches/composer/repo/https---mirrors.aliyun.com-composer/provider-fruitcake~php-cors.json from cache
Reading /Users/jayce/Library/Caches/composer/repo/https---mirrors.aliyun.com-composer/provider-fruitcake~php-cors~dev.json from cache
Reading /Users/jayce/Library/Caches/composer/repo/https---mirrors.aliyun.com-composer/provider-fruitcake~php-cors.json from cache
Reading /Users/jayce/Library/Caches/composer/repo/https---mirrors.aliyun.com-composer/provider-fruitcake~php-cors~dev.json from cache
Reading /Users/jayce/Library/Caches/composer/repo/https---mirrors.aliyun.com-composer/provider-fruitcake~php-cors.json from cache
Reading /Users/jayce/Library/Caches/composer/repo/https---mirrors.aliyun.com-composer/provider-fruitcake~php-cors.json from cache
Reading /Users/jayce/Library/Caches/composer/repo/https---mirrors.aliyun.com-composer/provider-fruitcake~php-cors~dev.json from cache
Reading /Users/jayce/Library/Caches/composer/repo/https---mirrors.aliyun.com-composer/provider-fruitcake~php-cors.json from cache
Reading /Users/jayce/Library/Caches/composer/repo/https---mirrors.aliyun.com-composer/provider-fruitcake~php-cors~dev.json from cache
Reading /Users/jayce/Library/Caches/composer/repo/https---mirrors.aliyun.com-composer/provider-fruitcake~php-cors.json from cache
Reading /Users/jayce/Library/Caches/composer/repo/https---mirrors.aliyun.com-composer/provider-fruitcake~php-cors~dev.json from cache
Reading /Users/jayce/Library/Caches/composer/repo/https---mirrors.aliyun.com-composer/provider-fruitcake~php-cors.json from cache
Reading /Users/jayce/Library/Caches/composer/repo/https---mirrors.aliyun.com-composer/provider-fruitcake~php-cors.json from cache
Reading /Users/jayce/Library/Caches/composer/repo/https---mirrors.aliyun.com-composer/provider-fruitcake~php-cors~dev.json from cache
Reading /Users/jayce/Library/Caches/composer/repo/https---mirrors.aliyun.com-composer/provider-fruitcake~php-cors.json from cache
Reading /Users/jayce/Library/Caches/composer/repo/https---mirrors.aliyun.com-composer/provider-fruitcake~php-cors~dev.json from cache
Reading /Users/jayce/Library/Caches/composer/repo/https---mirrors.aliyun.com-composer/provider-fruitcake~php-cors.json from cache
Reading /Users/jayce/Library/Caches/composer/repo/https---mirrors.aliyun.com-composer/provider-fruitcake~php-cors~dev.json from cache
Your requirements could not be resolved to an installable set of packages.
Problem 1
- laravel/framework[v11.9.0, v11.9.1, v11.9.2] require fruitcake/php-cors ^1.3 -> found fruitcake/php-cors[dev-feat-setOptions, dev-master, dev-main, dev-test-8.2, v0.1.0, v0.1.1, v0.1.2, v1.0-alpha1, v1.0-alpha2, v1.0-beta1, v1.0.0, v1.0.1, v1.1.0, 1.1.x-dev (alias of dev-main), v1.2.0, 1.2.x-dev (alias of dev-master)] but it does not match the constraint.
- Root composer.json requires laravel/framework ^11.9 -> satisfiable by laravel/framework[v11.9.0, v11.9.1, v11.9.2].
|
说是fruitcake/php-cors的包找不到v1.3.0
的版本,laravel/framework依赖了这个包,对应依赖如下:
1
2
3
|
"require": {
"fruitcake/php-cors": "^1.3"
}
|
通过命令进行检查:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
composer show --latest -a fruitcake/php-cors
# 以下为输出结果
name : fruitcake/php-cors
descrip. : Cross-origin resource sharing library for the Symfony HttpFoundation
keywords : symfony, cors, laravel
versions : dev-master, 1.2.x-dev, v1.2.0, 1.1.x-dev, v1.1.0, v1.0.1, v1.0.0, v1.0-beta1, v1.0-alpha2, v1.0-alpha1, v0.1.2, v0.1.1, v0.1.0, dev-main, dev-test-8.2, dev-feat-setOptions
latest : v1.2.0 released 2022-02-20, 2 years ago
type : library
license : MIT License (MIT) (OSI approved) https://spdx.org/licenses/MIT.html#licenseText
homepage : https://github.com/fruitcake/php-cors
source : [git] https://github.com/fruitcake/php-cors.git c70ea7b05b9a1b13d3196f235d5995b3deb93ae8
dist : [zip] https://api.github.com/repos/fruitcake/php-cors/zipball/c70ea7b05b9a1b13d3196f235d5995b3deb93ae8 c70ea7b05b9a1b13d3196f235d5995b3deb93ae8
names : fruitcake/php-cors
support
issues : https://github.com/fruitcake/php-cors/issues
source : https://github.com/fruitcake/php-cors/tree/master
autoload
psr-4
Fruitcake\Cors\ => src/
requires
php ^7.4|^8.0
symfony/http-foundation ^4.4|^5.4|^6|^7
requires (dev)
phpunit/phpunit ^9
squizlabs/php_codesniffer ^3.5
phpstan/phpstan ^1.4
|
检查阿里云镜像fruitcake/php-cors包的json,同样也是包的最新版本是v1.2.0(2022-02-20),该包在23年10月12日就发布了v1.3.0的版本,看来是阿里云已经很长时间没更新这个包了。
解决方法一
最简单直接的方式是换源,点我更换镜像源。
这里以腾讯云为例:
1
|
composer config -g repos.packagist composer https://mirrors.tencent.com/composer/
|
对应~/.composer/config.json
配置被修改如下:
1
2
3
4
5
6
7
8
|
{
"repositories": {
"packagist": {
"type": "composer",
"url": "https://mirrors.tencent.com/composer/"
}
}
}
|
该方式的缺点是,万一腾讯云也没更新该包的最新版本的话,问题依旧。
解决方法二
阿里云镜像源文档提到了canonical参数,配置如下:
1
2
3
4
5
6
7
8
9
10
|
{
"repositories": [
{
"description": "阿里云镜像",
"type": "composer",
"url": "https://mirrors.aliyun.com/composer/",
"canonical": false
}
]
}
|
解释是阿里云镜像站下载文件出错(例如404或者超时的情况等)或者包不是最新时,再从官方源上下载,这样确实能够解决阿里云包不是最新的问题。
但这个参数是怎么起作用的?怎么工作的呢?来细细研究一下。
composer在解决包依赖的时候,会从repositories
数组中上到下从镜像源中寻找包。
这里还有一个默认行为,packagist.org官方源会被隐式的添加到repositories
的最后一个,如果要禁用该行为,设置如下:
1
2
3
4
5
6
7
|
{
"repositories": [
{
"packagist.org": false
}
]
}
|
回到正题,canonical参数的官方解释,我大概复述一下,我们所说的镜像,其实在官方是指存储库,即repositories
属性中的配置,存储库又分为规范存储库(Canonical repositories)和非规范存储库(repositories non-canonical)。
在composer v2.x的版本中,默认所有存储库都是规范的(即"canonical": true
)。
而composer v1.x所有存储库都视为非规范存储库(即"canonical": false
)。
规范存储库有两个好处:
- 性能好,一旦在某个存储库中找到包以后,就会停止去扫描别的存储库去寻找包。
- 更安全,假设你设置了一个非规范的私有存储库,当你的项目中依赖一个私有包
foo/bar ^2.0
(假设版本是v2.4.3),之后当有人在packagist.org发布了一个foo/bar v2.999
的话,那么composer会读取到该包,因为v2.999的包更新,并且符合^2.0
的约束,那么你的项目可能会安装到预期以外的东西。规范存储库就不会有这个问题,因为在规范存储库中找到包以后就不会再去扫描别的存储库了。
解决方法三
正如上面所提到的,设置成非规范存储库是有风险的,并且安装过程会更慢。
解决办法也不是没有,可以多个镜像源混合使用,修改~/.composer/config.json
如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
{
"repositories": [
{
"type": "composer",
"url": "https://mirrors.aliyun.com/composer/",
"exclude": ["fruitcake/php-cors"]
},
{
"type": "composer",
"url": "https://mirrors.tencent.com/composer/"
}
]
}
|
exclude
的作用是排除寻找某个包,这样它就会从下一个规范仓库的镜像源中去寻找包。
- 缺点:
- 配置麻烦,如果出现正源有很多包都没更新的情况下,配置是个噩梦,这种情况下还是建议换源。
- 备用镜像源也没有最新包的情况下,问题依旧,还需再另外配置备用镜像源。
- 好处:性能更好,更安全。
解决方法四
自己搭建源,暂不开展
缺点:增加维护包的成本、搭建服务成本。
解决方法五
修改项目的composer.json
,设置查找包的方式:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
{
"repositories": [
{
"type": "package",
"package": {
"name": "wppd/aliyun-log-php-sdk",
"version": "1.0.4",
"dist": {
"url": "https://github.com/aliyun/aliyun-log-php-sdk/archive/refs/tags/v1.0.zip",
"type": "zip"
}
}
}
]
}
|
或者将包下载到本地,直接引用本地路径:
1
2
3
4
5
6
|
{
"repositories": [{
"type": "path",
"url": "/your_local_path/fruitcake/php-cors"
}]
}
|
缺点:需要额外配置项目的composer.json
以及维护包的版本。
镜像源
列一下常用的几个镜像源,请自行设置:
- 阿里云:https://mirrors.aliyun.com/composer/
- 华为云:https://mirrors.huaweicloud.com/repository/php/
- 腾讯云:https://mirrors.tencent.com/composer/
- 上海交通大学:https://packagist.mirrors.sjtug.sjtu.edu.cn
- 中国全量镜像:https://packagist.phpcomposer.com
- 官方源:https://repo.packagist.org
- 官方全球镜像:https://packagist.pages.dev
参考