滚动新闻 →
布莱克斯通法律评论为何影响深远 江苏一女子生下龙凤胎后起诉董事长 引热议 美俄勒冈小学枪击案4死 英勇教师扑倒枪手夺枪 蔷琵转中度台风 吴德荣:可能直扑台湾 加拿大家庭如何判断自己是否承担得起一套房子 为什么现金流对家庭财富管理如此重要 俄州枪案致4死 英雄父亲果断行动击毙枪手 超市自助结账藏陷阱 五大错误让你多花钱 纽约限制移民执法再升级 市长吁私人停车场拒绝ICE 美国购买私人游艇有哪些基本流程 俄罗斯媒体如何解读川普批评泽连斯基 乌克兰在大国交易中面临什么处境 演员为什么不能只看一次电影的片酬 川普对泽连斯基失去耐心 俄乌和平再添变数 美国八州联合起诉OpenAI 控其涉危害青少年 首秀表现欠佳律师资格疑云 白宫:新发言人卸任 乔任梁离世十年 好友陈乔恩:永远的少年 马斯克跑车倒挂飞天空中翻转!科幻片照进现实 川普政府起诉加州 逾2万身份不合法者收到选票 加拿大报税后发现婚姻状况填错怎么办 威廉·布莱克斯通如何影响美国法律 川普:将“一举拿下镐山” 终结伊朗冲突 日本发规模9.9级强震警报 8分钟后紧急撤回 扎卡里亚传过渡卸任中 川普:曾劝她重新考虑 俄研究员离奇死亡 苏联鼠疫研究藏疑云 加国亚省公投在即 分离议题牵动联邦省府关系 华为案再有新证 检方:避重就轻掩盖真实业务 甘肃252名幼儿铅中毒案 6人获刑 负责人判无期 美国肯德基终止与百事可乐合作 改为可口可乐 泽连斯基与匈牙利总理会谈 推两国关系正常化 白宫发言人回忆中国生活:连像样厕所都没有 北美买房时如何判断一套房子的长期居住价值 如何计算一个家庭真正拥有多少财富 第一次购买豪华游艇应该从哪里开始 经纪公司为什么会放弃一个曾经成功的演员 加拿大移民出新政:高薪职业加分无需LMIA 网信办下场“查”尊界事件 懂车帝下架测试视频 加州有逾两万名非公民投票 美司法部起诉 南加侨领宣国军持三国护照财力雄厚 保释再推迟 美国中期选举倒数 国会控制权成焦点 加拿大报税后发现家庭信息填错怎么办

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

发布时间: 2026-09-24 18:30:01    最后更新: 2026-10-16 09:16:50    阅读:80  约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