最稳方式是用精确版本号锁定包,如"monolog/monolog": "2.8.0";改完需运行composer update monolog/monolog同步lock文件;composer 2.2+可用--ignore跳过更新,但不解除自动加载。

composer install 时跳过更新某包
想让 composer install 完全不碰某个已安装的包,核心是别让它进依赖解析流程——最稳的方式是用 composer require 加 --no-update 配合手动修改 composer.lock,但普通人不该碰 lock 文件。真正可落地的做法是:把那个包从 require 移到 require-dev(如果它真不参与运行时),或者直接删掉再用 composer dump-autoload 清除 autoload 映射。不过更常见的情况其实是「不想升级」,不是「彻底禁用」。
用 version constraint 锁死扩展包版本
Composer 默认允许小版本更新(如 "monolog/monolog": "^2.8" 会升到 2.9.0),要锁死,就别用 ^ 或 ~,改用精确版本号:
-
"monolog/monolog": "2.8.0"—— 只认这一个版本,composer update不会动它 -
"monolog/monolog": "2.8.*"—— 允许2.8.0到2.8.999,但不会跨小版本 - 避免写
"2.8"这种不带补丁号的简写,不同 Composer 版本解析行为不一致
改完 composer.json 后必须运行 composer update monolog/monolog(指定包名),否则 lock 文件不会同步变更。
composer update 时临时忽略某个包
执行全局 composer update 时想跳过某包,直接在命令里排除它:
composer update --with-dependencies --ignore=laravel/framework
注意:--ignore 是 Composer 2.2+ 才支持的选项;低于这个版本只能用 composer update vendor/package1 vendor/package2 显式列出要更新的包,漏掉那个就行。另外,--ignore 不影响依赖关系检查,如果其他包要求更高版本,仍可能报冲突。
为什么 vendor/autoload.php 里还加载了被“锁定”的包?
锁定版本只控制安装行为,不影响自动加载机制。只要包还在 vendor/ 目录下、且被 composer.json 的 autoload 或 require 声明过,就会进 PSR-4/PSR-0 映射。常见误操作是:以为锁死版本就能“禁用功能”,结果该类照样能 new 出来。真要隔离,得配合代码层判断(比如检查 class_exists('SomeClass'))或重构调用路径。
最容易被忽略的是:lock 文件里的哈希校验和 vendor 目录内容强绑定。手动删掉某个包的文件夹、又没跑 composer install,后续任何 update 都可能把它拉回来——锁版本不是文件系统级的防护。










