composer update --dry-run 未报错但实际更新出问题,因其仅模拟依赖解析,不执行 post-update-cmd 钩子、不生成 autoload、不写入 bin 文件或配置,导致插件相关功能静默失效。

composer update --dry-run 为什么没报错,但实际更新后出问题
因为 composer update --dry-run 只模拟依赖图重算,不执行插件的 post-update-cmd 钩子逻辑。很多 Composer 插件(比如 phpstan/extension-installer、laravel/pint)会在钩子里做文件写入、配置生成或自动注册,这些动作在 dry-run 中完全跳过。
常见表现:dry-run 显示“12 packages updated”,实际运行后却出现 Class not found 或 Invalid configuration file;或者 vendor/bin 下的可执行文件消失。
- 检查项目是否启用了自定义插件:看
composer.json的"extra"或"scripts"字段里有没有调用post-update-cmd - 临时禁用钩子验证:加
--no-scripts参数再跑一次composer update,如果问题消失,说明是某个钩子导致的抖动 - 逐个排查插件:把
"require-dev"里的插件注释掉一半,再composer update --no-scripts,缩小范围
插件升级后自动修改了 config/*.php 却没生效
某些插件(如 spatie/laravel-ray、pestphp/pest-plugin)会在 post-update-cmd 中向 config/ 目录写入新配置文件,但 Laravel 或 Symfony 框架默认只加载 config/*.php 中已存在的文件——它不会自动扫描新增文件,也不会热重载。
结果就是:插件声称“已启用”,但实际功能不触发,日志里也无报错。
- 确认文件是否真被写入:
ls -l config/ray.php或git status config/ - 检查框架是否识别该配置:Laravel 运行
php artisan config:clear && php artisan config:cache;Symfony 要清var/cache/ - 注意权限问题:Docker 容器内运行时,插件生成的文件可能属 root,而 web server 进程无法读取
composer require 插件后命令行工具突然不可用
典型现象是装完 laravel/sail 或 phpunit/phpunit 后,vendor/bin/phpunit 找不到,或 sail 命令报 Permission denied。根本原因不是路径没加,而是插件安装过程中覆盖/重写了 vendor/bin 下的符号链接,且未正确设置可执行位。
- 先验证链接状态:
ls -l vendor/bin/ | grep phpunit,看是否指向不存在的路径或权限为-rw-r--r-- - 强制重建 bin 目录:
rm -rf vendor/bin && composer install(注意:这会重置所有 bin 链接) - 某些插件要求手动启用二进制:例如
php-cs-fixer需在composer.json的"bin"字段显式声明,否则不生成入口
插件热更新导致 autoload 加载失败
当插件自身包含 PSR-4 自动加载规则,并在更新后改变了命名空间映射或目录结构,而 composer dump-autoload 没被触发,就会出现 Class "Some\Plugin\Foo" not found —— 尤其多见于 dev 分支切换或 composer require vendor/plugin:dev-main 场景。
- 不要只信
composer update --with-dependencies,它不保证重刷 autoload - 必须手动执行:
composer dump-autoload -o(-o表示优化,生成 classmap) - 若插件含
autoload-files,检查它引入的文件是否还存在;composer show vendor/plugin可查其 autoload 配置 - 开发中频繁切分支时,建议加
"optimize-autoloader": true到composer.json的"config",避免每次都要手敲
插件热更新的抖动往往藏在钩子、autoload 和 bin 文件三处,它们不报错、不中断流程,却让功能静默失效。最危险的是你以为“更新完了”,其实只是依赖树变了,而真实运行环境还没同步。











