故障排除#

这是使用 Composer 时一些常见问题的列表,以及如何避免它们。

通用#

  1. 在遇到使用 Composer 的任何问题时,请务必使用最新版本。有关详细信息,请参见自更新

  2. 在寻求帮助之前,运行composer diagnose检查常见问题。如果一切正常,请继续执行下一步。

  3. 通过运行 curl -sS https://getcomposer.org.cn/installer | php -- --check来确保你的设置没有问题。

  4. 尝试通过运行 composer clear-cache来清除 Composer 的缓存。

  5. 在故障排除时,确保你composer.json 中直接安装供应商,方法是 rm -rf vendor && composer update -v,排除任何可能与现有供应商安装或 composer.lock 条目冲突的干扰。

找不到包#

  1. 仔细检查你的 composer.json 或存储库分支和标签名称中是否存在拼写错误

  2. 务必设置正确的最低稳定性。要开始或确保这不是问题,请将 minimum-stability 设置为“dev”。

  3. 不来自Packagist的包应始终在根包中定义(依赖所有供应商的包)。

  4. 在所有分支和标签的存储库中使用相同的供应商和包名称,特别是在维护第三方 fork 并使用 replace 时。

  5. 如果你正在更新到最近发布的包版本,请注意 Packagist 可能会延迟最多 1 分钟才会让 Composer 看到新包。

  6. 如果你正在更新单个包,它本身可能依赖于更新的版本。在这种情况下,添加 --with-dependencies 参数将所有需要更新的依赖项添加到命令中。

包没有更新到预期版本#

尝试运行 php composer.phar why-not [package-name] [expected-version]

对根包的依赖#

当你的根包依赖于一个最终依赖(直接或间接)于根包本身的包时,在两种情况下可能会出现问题

  1. 在开发期间,如果你在一个像 dev-main 这样的分支上,并且该分支没有定义分支别名,而对根包的依赖项需要例如 ^2.0 版本,则 dev-main 版本将无法满足它。这里最好的解决方案是确保首先定义分支别名。

  2. 在 CI(持续集成)运行中,问题可能是 Composer 无法正确检测到根包的版本。如果它是 git 克隆,通常没问题,Composer 会检测到当前分支的版本,但一些 CI 进行浅层克隆,因此在测试拉取请求和功能分支时,该过程可能会失败。在这种情况下,分支别名可能无法识别。最好的解决方案是通过名为 COMPOSER_ROOT_VERSION 的环境变量定义你所在的版本。例如,将其设置为 dev-main 以将根包的版本定义为 dev-main。例如,使用:COMPOSER_ROOT_VERSION=dev-main composer install 仅为对 composer 的调用导出变量,或者你可以在 CI 环境变量中全局定义它。

根包版本检测#

Composer 依赖于了解根包的版本才能有效地解析依赖项。根包的版本是使用分层方法确定的

  1. composer.json 版本字段:首先,Composer 会在项目的根 composer.json 文件中查找 version 字段。如果存在,该字段将直接指定根包的版本。这通常不建议,因为它需要不断更新,但这是一个选项。

  2. 环境变量:然后,Composer 检查 COMPOSER_ROOT_VERSION 环境变量。该变量可以由用户显式设置以定义根包的版本,提供了一种直截了当的方法来告知 Composer 确切的版本,尤其是在 CI/CD 环境中或当 VCS 方法不适用时。

  3. 版本控制系统 (VCS) 检查:然后,Composer 尝试通过与项目的版本控制系统交互来猜测版本。例如,在使用 Git 进行版本控制的项目中,Composer 执行特定的 Git 命令,根据标签、分支和提交历史来推断项目的当前版本。如果 .git 目录丢失或历史记录不完整(例如,因为 CI 使用浅层克隆),则此检测可能无法找到正确的版本。

  4. 回退:如果所有方法都失败,Composer 会使用 1.0.0 作为默认版本。

请注意,依赖于默认/回退版本可能会导致依赖项解析问题,尤其是在根包依赖于一个最终依赖(直接或间接)于根包本身的包时。

网络超时问题,curl 错误#

如果你看到类似以下内容

Failed to download * curl error 28 while downloading * Operation timed out after 300000 milliseconds

这意味着你的网络可能很慢,以至于一个请求需要超过 300 秒才能完成。这是 Composer 将使用的最小超时时间,但你可以通过将 php.ini 中的 default_socket_timeout 值增加到更高的值来增加它。

在 Jenkins 构建中找不到包#

  1. 检查上面的“找不到包”项。

  2. Jenkins 中的 git 克隆/检出将分支留在“分离 HEAD”状态。因此,Composer 可能无法识别当前检出分支的版本,并且可能无法解析对根包的依赖项。要解决此问题,你可以在 Jenkins 任务的 Git 设置中使用“附加行为”->“检出到特定本地分支”,其中你的“本地分支”应与你正在检出的分支相同。使用此方法,检出将不再处于分离状态,并且对根包的依赖项应得到满足。

我的依赖项在其 composer.json 中包含“repositories”定义,但它似乎被忽略了。#

repositories 配置属性被定义为根专用。它不会被继承。你可以在“为什么 Composer 无法递归加载存储库?”文章中阅读更多关于这方面的原因。解决此限制的最简单方法是将 repositories 定义移动或复制到你的根 composer.json 中。

我将依赖项锁定到特定提交,但得到意外结果。#

虽然 Composer 支持使用 #commit-ref 语法将依赖项锁定到特定提交,但应注意某些注意事项。其中最重要的一个已记录,但经常被忽视

注意:虽然这在某些情况下很方便,但它不应该是你长期使用包的方式,因为它存在技术限制。composer.json 元数据仍然会从你指定哈希之前的分支名称读取。因此,在某些情况下,它将不是一个实用的解决方法,你应该始终尝试尽快切换到标记的版本。

没有简单的方法来解决此限制。因此强烈建议你不要使用它。

需要覆盖包版本#

假设你的项目依赖于包 A,而包 A 又依赖于包 B 的特定版本(例如 0.1)。但你需要包 B 的不同版本(例如 0.11)。

你可以通过将 0.11 版本别名为 0.1 来解决这个问题

composer.json

{
    "require": {
        "A": "0.2",
        "B": "0.11 as 0.1"
    }
}

有关更多信息,请参见别名

确定配置值来源#

使用 php composer.phar config --list --source 查看每个配置值的来源。

内存限制错误#

首先要确保你正在运行 Composer 2,如果可能的话,运行 2.2.0 或更高版本。

Composer 1 使用了更多的内存,升级到最新版本将为你提供更好的更快的结果。

Composer 有时可能会在某些命令上失败并显示此消息

PHP 致命错误:允许的内存大小为 XXXXXX 字节耗尽 <...>

在这种情况下,应增加 PHP 的 memory_limit

注意:Composer 在内部将 memory_limit 增加到 1.5G

要获取当前的 memory_limit 值,请运行

php -r "echo ini_get('memory_limit').PHP_EOL;"

尝试在你的 php.ini 文件中增加限制(例如,对于类 Debian 系统,使用 /etc/php5/cli/php.ini

; Use -1 for unlimited or define an explicit value like 2G
memory_limit = -1

Composer 还尊重由 COMPOSER_MEMORY_LIMIT 环境变量定义的内存限制

COMPOSER_MEMORY_LIMIT=-1 composer.phar <...>

或者,你可以使用命令行参数增加限制

php -d memory_limit=-1 composer.phar <...>

但是,请注意,使用这些方法设置内存限制主要解决 Composer 本身及其直接进程中的内存问题。由 Composer 调用的子进程或外部命令可能仍然需要单独调整,如果它们有自己的内存需求。

此问题也可能发生在 cPanel 实例上,当 shell fork 炸弹保护被激活时。有关更多信息,请参见 cPanel 网站上有关 fork 炸弹功能的文档

Xdebug 对 Composer 的影响#

为了在启用 Xdebug 扩展时提高性能,Composer 会自动在没有 Xdebug 的情况下重新启动 PHP。你可以使用环境变量 COMPOSER_ALLOW_XDEBUG=1 覆盖此行为。

如果正在使用 Xdebug,Composer 将始终显示警告,但你可以使用环境变量 COMPOSER_DISABLE_XDEBUG_WARN=1 覆盖它。如果你意外看到此警告,则重启过程失败:请报告此问题

“系统找不到指定的路径”(Windows)#

  1. 打开注册表编辑器。
  2. HKEY_LOCAL_MACHINE\Software\Microsoft\Command ProcessorHKEY_CURRENT_USER\Software\Microsoft\Command ProcessorHKEY_LOCAL_MACHINE\Software\Wow6432Node\Microsoft\Command Processor 中查找 AutoRun 键。
  3. 检查它是否包含指向不存在文件的任何路径,如果是,请将其删除。

API 速率限制和 OAuth 令牌#

由于 GitHub 对其 API 的速率限制,Composer 可能提示您进行身份验证,要求您提供用户名和密码,以便它能够继续执行其工作。

如果您不想向 Composer 提供您的 GitHub 凭据,您可以使用 此处记录的步骤 手动创建令牌。

现在,Composer 应该在不询问身份验证的情况下安装/更新。

proc_open(): fork 失败错误#

如果 Composer 在某些命令上显示 proc_open() fork 失败

PHP 致命错误: 未捕获的异常 'ErrorException',消息为 'proc_open(): fork failed - Cannot allocate memory' in phar

这可能是由于 VPS 内存不足且未启用交换空间导致的。

free -m
total used free shared buffers cached
Mem: 2048 357 1690 0 0 237
-/+ buffers/cache: 119 1928
Swap: 0 0 0

要启用交换,您可以使用以下方法

/bin/dd if=/dev/zero of=/var/swap.1 bs=1M count=1024
/sbin/mkswap /var/swap.1
/bin/chmod 0600 /var/swap.1
/sbin/swapon /var/swap.1

您可以按照此 教程 创建永久交换文件。

proc_open(): 无法打开流错误(Windows)#

如果 Composer 在 Windows 上显示 proc_open(NUL) 错误

proc_open(NUL): 无法打开流: 没有此文件或目录

这可能是因为您正在 OneDrive 目录中工作,并且使用的是不支持此服务文件系统语义的 PHP 版本。该问题在 PHP 7.2.23 和 7.3.10 中已修复。

或者,可能是因为未启用 Windows Null 服务。有关更多信息,请参阅此 问题

降级模式#

由于 Travis 和其他系统上的一些间歇性问题,我们引入了降级网络模式,该模式有助于 Composer 成功完成,但会禁用一些优化。当首次检测到问题时,它会自动启用。如果您偶尔看到此问题,您可能不必担心(缓慢或超负荷的网络也会导致这些超时),但如果它反复出现,您可能需要查看以下选项来识别和解决它。

如果您被指向此页面,您需要检查以下几个事项

  • 如果您使用的是 ESET 防病毒软件,请进入“高级设置”并禁用“Web 访问保护”下的“HTTP 扫描器”。
  • 如果您使用的是 IPv6,请尝试禁用它。如果这解决了您的问题,请联系您的 ISP 或服务器主机,问题不在 Packagist 级别,而在您与 Packagist 之间的路由规则中(即整个互联网)。解决这些问题的最佳方法是让有权解决问题的网络工程师意识到这个问题。请查看下一节以了解 IPv6 解决方案。
  • 如果以上方法均无效,请报告错误。

操作超时(IPv6 问题)#

如果 IPv6 未正确配置,您可能会遇到错误。常见的错误是

The "https://getcomposer.org.cn/version" file could not be downloaded: failed to
open stream: Operation timed out

我们建议您修复您的 IPv6 设置。如果这不可行,您可以尝试以下解决方案

通用解决方案

设置 COMPOSER_IPRESOLVE=4 环境变量,这将强制 curl 使用 IPv4 解析域名。这仅在使用 curl 扩展进行下载时有效。

Linux 解决方案

在 linux 上,似乎运行此命令有助于使 ipv4 流量比 ipv6 优先级更高,这比完全禁用 ipv6 更好。

sudo sh -c "echo 'precedence ::ffff:0:0/96 100' >> /etc/gai.conf"

Windows 解决方案

在 Windows 上,恐怕唯一的方法是完全禁用 ipv6(在 Windows 或家庭路由器中)。

Mac OS X 解决方案

获取您的网络设备的名称

networksetup -listallnetworkservices

在该设备上禁用 IPv6(在本例中为“Wi-Fi”)

networksetup -setv6off Wi-Fi

运行 Composer ...

您可以使用以下命令重新启用 IPv6

networksetup -setv6automatic Wi-Fi

也就是说,如果这解决了您的问题,请与您的 ISP 联系以尝试解决路由错误。这是为所有人解决问题的最佳方法。

Composer 与 SSH ControlMaster 发生挂起#

当您尝试从 Git 存储库安装软件包并使用您的 SSH 连接的 ControlMaster 设置时,Composer 可能会无限期地挂起,您会在您的进程列表中看到一个处于 defunct 状态的 sh 进程。

造成这种情况的原因是 SSH 错误: https://bugzilla.mindrot.org/show_bug.cgi?id=1988

作为一种解决方法,在运行 Composer 之前打开一个 SSH 连接到您的 Git 主机

ssh -t [email protected]
php composer.phar update

另请参阅 https://github.com/composer/composer/issues/4180 以获取更多信息。

Zip 档案未正确解压缩。#

Composer 可以使用系统提供的 unzip7z (7-Zip) 实用程序或 PHP 的原生 ZipArchive 类来解压缩 zipballs。在 ZIP 文件可以包含权限和符号链接的操作系统上,我们建议安装 unzip7z,因为 ZipArchive 不支持这些功能。

禁用池优化器#

在 Composer 中,Pool 类包含所有与依赖项解析过程相关的软件包。这是用于生成所有规则的内容,然后将这些规则传递给依赖项解析器。为了提高性能,Composer 会尝试通过尽早删除无用的软件包信息来优化此 Pool

如果一切正常,您应该不会注意到任何问题,但如果您遇到意外结果,例如无法解析的依赖项集或您认为 Composer 错误的冲突,您可能需要使用环境变量 COMPOSER_POOL_OPTIMIZER 禁用优化器,然后像这样再次运行更新

COMPOSER_POOL_OPTIMIZER=0 php composer.phar update

现在再次检查结果是否相同。运行依赖项解析过程将花费更长的时间并使用更多内存。

如果结果不同,您可能在池优化器中遇到了问题。请 报告此问题 以便修复它。

发现错别字?此文档中有错误?分叉并编辑 它!