滚动新闻 →
陕西商南凶案嫌犯逃亡两日后深山自尽 俄方以制裁为由接管日烟资产 日本敦促立即撤销 《白衣逆行者》撤档引争议 电影方未回应集体抵制 男子向警车投掷汽油瓶引发火灾 警方跨区追捕10小时擒凶 中国女厕偷拍黑产蔓延 超14万女性受害 河北中学厕所冲突致13岁学生死亡 4人获刑 从古典文学看中国人的时间观念 内部人士曝马兴瑞接班饭局内幕 触犯习大忌 经络理论在传统医学中的形成 印章上的篆书为什么特别多 中共大搞3C检查 多地五金店“恐慌式闭店” 巴拉圭银行倒闭 总统潘尼亚抢先国会弹劾提离职 赖均辅逆转许皓鋐 玄乐杯决赛第三局上演惊天逆转 刘云平将成美国国会亚裔最高职位者 民主党夺回国会布局完成 医药高官余艳红主动投案 涉及与习御医曾益新密切关联 如何教育孩子为自己的行为承担后果 欧洲多国航班接连遭遇炸弹恐吓 超25架客机受影响 进化骗局(34) 造假打磨 世界认可 陆配亚亚返乡后展示卫星影像 引发两岸舆论争议 民主党内部派系博弈加剧 四大政治挑战浮现 为什么剪辑不是简单地把片段拼起来 纽约布鲁克林住宅火灾致6人遇难 锂电池或成主因 台湾AI产业带动经济回暖 百货业预期景气延续至2027年 万斯直指伊朗战争影响选情 赫格塞斯或遭弹劾 台股重挫逾3700点失守年线 新台币跌破33元创逾1年半新低 退休夫妇邮轮退休梦破灭 突发停运令203名住户陷入困境 美国国会权力更迭 或重塑全球外交格局 APEC暗潮涌动 美中俄会晤能否成行留悬念 晚清为什么不断出现改革与失败 加拿大公布新预算案 卡尼推动经济自主 赤字引发关注 台湾退役军官涉中共选举干预遭限制出境 中共对台跨境镇压升级 九大手段威胁民主自由 美军加速部署无人机防御体系 涉及超2.5万套装备 纽约布鲁克林木质排屋火灾致6死9伤 美股四大指数重挫 AI科技股集体暴跌 英伟达特斯拉跌逾9% 小户型如何利用墙角空间 欧洲多架航班遭遇炸弹威胁 战斗机紧急护航 加拿大面临中共渗透风险 专家呼吁加强安全审查 马兴瑞贪腐25年被起诉 习彭人脉遭冲击 黄之锋被判十年监禁 国际社会谴责中共人权问题

composer.json 应该怎么写?PHP 项目的依赖和版本管理基础

发布时间: 2026-09-24 18:30:01    最后更新: 2026-11-06 02:01:35    阅读:111  约4 分钟阅读     

composer.json 应该怎么写?PHP 项目的依赖和版本管理基础
图片说明:示意图   图片来源:Public Domain(公有领域)
对于 PHP 项目来说,composer.json 并不是一个简单的“安装软件包列表”,而是整个项目依赖关系的声明文件。项目需要什么 PHP 版本,需要哪些第三方库,生产环境和开发环境分别依赖什么,以及项目应该如何自动加载自己的代码,都可以在这个文件中定义。 理解 composer.json,实际上是在理解现代 PHP 项目是怎样管理依赖的。 一个最简单的 PHP 项目,可以从这样的 composer.json 开始: { "name": "example/my-project", "description": "A PHP application", "type": "project", "require": { "php": "^8.2", "monolog/monolog": "^3.0" }, "require-dev": { "phpunit/phpunit": "^11.0" }, "autoload": { "psr-4": { "App\\": "src/" } } } 这里最重要的是 require 和 require-dev。 require 表示项目运行所需要的依赖。例如一个网站运行时需要日志库、数据库组件或者 HTTP 客户端,这些应该放在 require 中。 require-dev 则用于开发和测试。例如 PHPUnit、PHPStan、PHP_CodeSniffer 等工具通常只在开发环境使用。生产服务器执行 composer install --no-dev 时,可以不安装这些开发依赖。 这两个字段的区别并不是“重要依赖”和“不重要依赖”,而是“生产运行时需要”与“开发阶段需要”。 Composer 的核心机制是依赖解析。 例如项目声明: { "require": { "monolog/monolog": "^3.0" } } 这并不是告诉 Composer “永远安装 Monolog 3.0.0”,而是在告诉 Composer,项目接受符合这个版本约束的 Monolog 版本。 Composer 随后会分析这个包自己的依赖,以及其他直接依赖和间接依赖之间的关系,寻找一个能够同时满足所有版本约束的依赖集合。 这里也需要纠正一个常见误解。 如果项目 A 需要某个库的 ^1.0,项目中的另一个依赖需要同一个库的 ^2.0,Composer 并不会简单地“优先选择最新版本”然后强行安装。 如果两个约束无法同时满足,Composer 通常会报告依赖冲突。解决方案是升级或降级其中一个依赖、调整版本约束,或者寻找兼容的版本组合。 这也是 Composer 和简单复制 PHP 类库最大的区别。 版本号写法尤其重要。 1.2.3 表示一个非常具体的版本约束,而 ^1.2.3 和 ~1.2.3 则允许一定范围内的版本。 对于 Composer 常见的语义版本规则,可以简单理解为: ^1.2.3 允许 1.x 的兼容更新,但不进入 2.0.0 ~1.2.3 允许 1.2.x 的更新,但通常不会进入 1.3.0 1.2.3 只允许这个版本 不过,实际版本约束还受到 Composer 对不同主版本以及零版本号规则的处理影响,所以不能把 ^ 永远理解成“只要小于下一个整数版本”。对于正常遵循语义化版本的库,^1.2.3 最常见的含义是允许 >=1.2.3 <2.0.0。 很多项目最初会把版本写得非常死,例如: "monolog/monolog": "3.0.0" 这样做确实可以限制版本变化,但对于普通应用项目,通常没有必要把所有依赖都固定到一个具体版本。Composer 本身就通过 composer.lock 来记录经过解析后的具体版本。 这两个文件的职责不同。 composer.json 描述的是“项目允许使用什么依赖”。 composer.lock 描述的是“这一次解析之后,实际使用了哪些具体版本”。 因此,对于应用程序项目,通常应该把 composer.lock 一起提交到 Git。 例如开发人员运行: composer update Composer 会重新解析依赖,并按照 composer.json 中的约束寻找新的可用版本,然后更新 composer.lock。 而在服务器部署时,通常使用: composer install --no-dev 如果存在 composer.lock,Composer 会根据锁定文件安装已经确定的版本,而不是每次部署都重新选择一套依赖。 这也是为什么不要把“composer.json 改了但 composer.lock 没改”当成正常的版本管理方式。如果修改了依赖声明,通常应该让 Composer 重新解析相关依赖,并把更新后的 composer.lock 一起提交。 如果只想更新某一个依赖,也可以针对具体包执行更新,而不是每次让整个依赖树全部升级。 Composer 的另一个重要功能是自动加载。 现代 PHP 项目通常不需要手动写几十个 require 或 require_once。例如: "autoload": { "psr-4": { "App\\": "src/" } } 表示 App 命名空间下的类可以按照 PSR-4 规则从 src/ 目录自动加载。 项目入口文件通常只需要: require __DIR__ . '/vendor/autoload.php'; 然后就可以使用 Composer 管理的类。 如果修改了 autoload 配置,需要重新生成自动加载文件: composer dump-autoload 生产环境还可以使用: composer dump-autoload -o 优化自动加载。 这里也需要纠正原文中的一个概念:optimize-autoloader 并不是“加快依赖解析速度”。它主要影响的是 Composer 生成和运行时的自动加载机制,而不是 Composer 如何解决版本冲突。 如果希望把自动加载优化作为项目配置的一部分,可以使用: { "config": { "optimize-autoloader": true } } 大型生产项目通常也会在部署时使用优化自动加载。 PHP 版本约束同样应该写进 composer.json。 例如: "require": { "php": "^8.2" } 这意味着项目的运行环境必须满足相应的 PHP 版本要求。 如果开发机器运行 PHP 8.3,而生产服务器只有 PHP 8.1,Composer 就应该尽早暴露这个问题,而不是等程序上线以后才发现语法或者依赖无法运行。 还有一个容易混淆的配置是 config.platform。 正确的结构应该是: { "config": { "platform": { "php": "8.2.0" } } } 而不是把 platform 直接放在 composer.json 顶层。 config.platform 的作用,是告诉 Composer 在依赖解析时按照指定的平台版本进行判断。例如开发人员电脑安装的是 PHP 8.3,但生产环境实际上是 PHP 8.2,那么可以通过 platform 设置让 Composer按照 PHP 8.2 的兼容条件解析依赖。 不过它并不会把电脑上的 PHP 8.3 “变成” PHP 8.2。 这一点非常重要。 如果服务器实际上只有 PHP 8.1,那么 composer.json 写: "platform": { "php": "8.2.0" } 并不会 magically 把 PHP 8.1 升级成 PHP 8.2。它只是改变 Composer 的依赖解析视角。因此部署前仍然必须检查服务器实际 PHP 版本。 Composer 还会把 PHP 扩展当作平台依赖。 例如: "require": { "php": "^8.2", "ext-curl": "*", "ext-mbstring": "*", "ext-gd": "*" } 这里的 ext-curl、ext-mbstring 和 ext-gd 不是普通 Composer 软件包,而是 PHP 环境提供的扩展。 Composer 可以检查它们是否存在,但 Composer 并不会像安装普通 PHP 包一样替你安装这些扩展。 遇到“为什么 Composer 安装失败”的问题时,可以使用: composer show --platform 查看当前 PHP 环境和已经提供的平台依赖。 处理复杂依赖冲突时,composer why 和 composer why-not 非常有用。 例如: composer why monolog/monolog 可以帮助查看为什么项目需要这个包。 而: composer why-not monolog/monolog 3.0.0 可以用于分析为什么某个指定版本无法安装。 这比遇到冲突以后直接删除 composer.lock 或者随便更换一个依赖包更加可靠。 对于私有依赖,也可以在 composer.json 中声明自定义仓库。例如公司内部维护的 Git 仓库: { "repositories": [ { "type": "vcs", "url": "https://gitlab.example.com/team/private-package.git" } ], "require": { "company/private-package": "^1.0" } } 不过 repositories 的作用主要是告诉 Composer 去哪里寻找包,并不等于把 GitLab、GitHub 等服务的账号密码直接写进 composer.json。 认证信息应该通过 Composer 的认证机制、环境变量、CI/CD 的安全凭据等方式处理。不要把访问令牌、密码或者私钥直接提交到 Git 仓库。 Composer 还支持 scripts,可以把项目中的常用操作统一起来。 例如: { "scripts": { "test": "phpunit", "analyse": "phpstan analyse", "cs": "phpcs" } } 之后可以直接运行: composer test composer analyse composer cs 这样团队成员不需要记住一大串命令。 不过,自动执行脚本也需要谨慎设计。尤其是 post-install-cmd、post-update-cmd 这类生命周期脚本,如果里面放置大量修改文件或者执行外部程序的操作,部署环境应该提前审查,避免第三方依赖安装时产生不必要的副作用。 安全方面,现在 Composer 项目应该把依赖审计作为正常开发流程的一部分。 可以运行: composer audit 检查当前依赖是否存在已知安全漏洞。 如果发现漏洞,不能简单理解成“Composer 有问题”。Composer 只是把依赖关系和已知安全公告呈现出来,真正需要处理的是存在问题的第三方包,以及是否存在可以升级到的安全版本。 一个实际项目的 composer.json 通常不需要写得非常复杂。 例如一个普通 PHP 网站可能已经足够: { "name": "mnewstv/website", "description": "MNewsTV website", "type": "project", "require": { "php": "^8.2", "ext-curl": "*", "ext-mbstring": "*" }, "require-dev": { "phpunit/phpunit": "^11.0" }, "autoload": { "psr-4": { "App\\": "src/" } }, "config": { "optimize-autoloader": true, "sort-packages": true } } 然后执行: composer install Composer 会建立 vendor/ 目录,并生成相应的自动加载文件。 通常不需要把 vendor/ 目录提交到 Git,因为它可以根据 composer.json 和 composer.lock 在部署时重新安装。 一个比较规范的 PHP 项目流程通常是这样的: 开发阶段修改 composer.json,然后执行 Composer 命令解析依赖;Composer 更新 composer.lock;开发人员测试程序;composer.json 和 composer.lock 一起提交到版本控制系统;生产环境执行 composer install --no-dev;最后根据部署环境生成优化后的 autoload。 这样,项目依赖就从“某个人电脑上安装了哪些 PHP 包”,变成了可以被代码库明确描述、重复安装和部署的工程配置。 理解 composer.json 最重要的不是记住几十个字段,而是理解几个文件之间的关系:composer.json 负责声明项目需要什么,composer.lock 负责锁定这次解析得到的具体版本,vendor 负责保存实际安装的依赖,vendor/autoload.php 负责把这些类加载进 PHP 程序。 当这几个概念分清楚以后,Composer 就不再只是一个“下载 PHP 插件的工具”,而成为 PHP 项目控制依赖、版本、自动加载、开发工具和部署环境的重要基础设施。对于一个需要长期维护的 PHP 项目来说,真正麻烦的从来不是安装第一个包,而是几年之后依然能够知道这个项目为什么依赖它、依赖哪个版本,以及升级以后会发生什么。

喜欢这篇报道?

使用下面的功能,方便以后继续阅读和分享 MNewsTV

设为 Google 新闻首选来源 让 Google 新闻优先显示 MNewsTV 的最新报道 ›
★ 我的收藏 查看已经收藏的文章
关于文章收藏 收藏不需要注册帐号,收藏信息仅保存在当前浏览器中。 删除收藏请进入「我的收藏」进行管理。
分享这篇报道

捐助(Paypal): https://www.paypal.me/observeccp
订阅中国观察电报 Telegram : https://t.me/s/ObserveCCP