Composer如何管理多个项目的依赖?(全局与局部区别)

1次阅读

该用 composer install;它读取 composer.lock 安装锁定版本,确保环境一致,仅在需升级依赖时才用 composer update 并建议指定包名。

Composer如何管理多个项目的依赖?(全局与局部区别)

composer install 和 composer update 到底该用哪个?

composer installcomposer.lock,只装锁定版本;composer update 忽略 lock 文件,重新解析依赖树、升级到符合约束的最新版本。

  • 新项目首次部署或 CI 构建时,必须用 composer install —— 否则可能装出和开发环境不一致的包版本
  • 只有明确要升级依赖(比如修安全漏洞、用新特性)才运行 composer update,且建议加具体包名: composer update monolog/monolog,避免连带升级一无关包
  • composer update 在团队协作中容易引发意外:比如某人本地跑了一次,提交了新 composer.lock,其他人 git pull 后再 composer install 就会装上不同版本 —— 这不是 bug,是 lock 文件本意,但常被忽略

多个项目共用同一套 vendor 怎么办?

不能。Composer 没有“全局 vendor 目录”机制,每个项目必须有独立的 vendor/ 目录。

  • 全局安装(composer global require)只影响 ~/.composer/vendor/~/.composer/vendor/bin/,这些二进制命令(如 phpunitlarastan)可被 shell 找到,但不会被任何项目的 autoloader 加载
  • 试图 symlink 多个项目共享一个 vendor 会导致 autoload 冲突、类加载失败、composer dump-autoload 失效
  • 真正节省磁盘空间的方法是启用 Composer 的 cache-dir(默认已开),它复用下载的 zip 包和解压缓存,而不是复用 vendor

为什么 vendor/autoload.php 不能跨项目 require?

因为每个项目的 vendor/autoload.php 是根据自身 composer.json 生成的,只认识自己声明的命名空间和路径。

  • 假设项目 A 声明了 "psr-4": {"App": "src/"},项目 B 声明了 "psr-4": {"MyApp": "app/"},它们的 autoloader 注册规则完全不同
  • 如果在项目 B 中 require '../project-a/vendor/autoload.php',那项目 A 的 App 类会被加载,但项目 B 自己的类可能反而找不到 —— autoloader 顺序错乱,class_exists() 行为不可控
  • 正确做法:把可复用的逻辑抽成独立包,发布到私有仓库或 Packagist,然后各项目通过 composer require 引入,由 Composer 统一管理加载

全局命令和局部命令冲突时谁生效?

Shell 查找命令时只看 $PATH,跟 Composer 无关;但执行时是否走全局安装的二进制,取决于 $PATH 中哪个目录排更前。

  • composer global bin 显示全局 bin 目录(通常是 ~/.composer/vendor/bin
  • 你执行 phpunit 时,系统从 $PATH 左到右找第一个匹配的 phpunit 文件
  • 如果项目里也通过 composer require --dev phpunit/phpunit 装了,它的 vendor/bin/phpunit 就在当前目录下,但除非你显式写成 ./vendor/bin/phpunit 或把 ./vendor/bin 加进 $PATH,否则不会优先使用它
  • 容易踩的坑:CI 脚本里直接写 phpunit,结果跑的是全局旧版本,而本地开发用的是项目内新版 —— 应统一用 ./vendor/bin/phpunit

路径和加载机制比表面看起来更刚性,改错一处就可能让类找不到、命令行为漂移、lock 文件失效——不是配置问题,是 Composer 的设计前提就拒绝模糊边界。

text=ZqhQzanResources