Composer 怎么使用?从安装第一个 PHP 扩展包开始理解依赖管理
很多刚开始学习 PHP 的开发者第一次接触 Composer 时,往往会把它理解成一个“下载 PHP 类库的工具”。输入一条命令,网上下载几个文件,项目就可以开始使用。但如果只把 Composer 理解到这个层面,真正遇到版本冲突、团队协作、服务器部署或者依赖升级时,很快就会发现事情没有这么简单。
Composer 的核心并不是“下载”,而是依赖管理。它负责描述一个 PHP 项目需要哪些软件包、这些软件包允许使用什么版本、它们之间还依赖哪些其他软件包,并把最终解析出来的版本固定下来。与此同时,Composer 还提供自动加载机制,让 PHP 项目不再需要到处手写 require 和 include。
理解 Composer 最好的办法,不是背几十条命令,而是从安装一个包开始,看清楚 composer.json、composer.lock 和 vendor 三者到底分别负责什么。
安装 Composer 之前先确认 PHP 环境
Composer 本身运行在 PHP 环境中,所以第一步不是安装某个 PHP 包,而是确认电脑上的 PHP 可以正常工作。
打开终端执行:
php -v
目前 Composer 最新稳定版本对 PHP 7.2+ 用户可用;如果是比较老的 PHP 环境,也可能需要使用相应的旧版 Composer。对于新项目,更建议使用受支持的 PHP 8.x 版本,而不是为了迁就旧环境长期停留在已经过时的 PHP 版本上。
Linux 或 macOS 可以按照 Composer 官方安装方式安装。Windows 用户通常也可以使用 Composer 官方提供的 Windows 安装程序。
安装完成后执行:
composer --version
如果能够显示 Composer 版本号,说明命令行已经可以找到 Composer。
这里还有一个很容易被新手忽略的问题:Composer 检查的并不只有 PHP 版本。PHP 扩展本身也可以成为项目依赖,例如某个程序要求 ext-mbstring、ext-curl 或 ext-gd。这些扩展不是由普通的 composer require 自动下载到 vendor 目录中的,而是属于 Composer 所说的平台依赖。Composer 会检查当前 PHP 环境是否满足这些要求。
因此,“Composer 安装成功”并不等于“所有 PHP 项目都能运行”。Composer 能帮你管理 PHP 包,也能检查 PHP 和扩展是否符合依赖要求,但它不是一个万能的 PHP 扩展安装器。
创建第一个 Composer 项目
假设我们从一个空目录开始:
mkdir my-project
cd my-project
可以运行:
composer init
Composer 会询问项目名称、描述、作者以及依赖等信息,最终生成:
composer.json
这就是项目的依赖描述文件。
一个最简单的 composer.json 可能类似这样:
{
"require": {
"symfony/console": "^7.0"
}
}
这里最重要的是理解 require。
它不是告诉 Composer“把这个文件下载下来”,而是在告诉 Composer:
“我的项目需要这个软件包,并且允许使用满足这个版本约束的版本。”
Composer 随后会进一步分析这个软件包依赖什么。
这就是依赖管理真正开始发挥作用的地方。
安装第一个 PHP 包
例如安装 Symfony Console:
composer require symfony/console
Composer 会解析 symfony/console 本身以及它需要的其他依赖,然后把符合版本约束的软件包安装到:
vendor/
目录。
这里最好纠正一个常见说法:Composer 管理的是 PHP package,也就是 PHP 软件包,并不等同于“PHP 扩展”。
例如:
composer require symfony/console
安装的是 PHP 用户空间代码包。
而:
ext-mbstring
ext-curl
ext-gd
属于 PHP 平台扩展。某个 Composer 包可以声明自己依赖这些扩展,但 Composer 通常只是检查当前 PHP 环境是否已经提供这些扩展,而不是把它们像普通 PHP 包一样下载进 vendor。
这个区别对于排查服务器部署问题非常重要。
vendor、composer.json 和 composer.lock 到底是什么
安装完成以后,项目通常会出现几个关键部分。
composer.json 是“项目想要什么”。
例如:
{
"require": {
"symfony/console": "^7.0"
}
}
它描述的是依赖以及允许接受的版本范围。
composer.lock 则是“这一次到底决定安装了什么”。
它会记录依赖解析之后得到的具体版本以及相关信息。这样开发电脑、测试服务器和生产服务器就可以使用同一套确定的依赖版本。
vendor/ 则是“实际安装到电脑上的代码”。
所以可以把三者简单理解为:
composer.json 项目需要什么
composer.lock 最终确定安装什么
vendor/ 实际安装在哪里
对于 PHP 应用程序,composer.lock 通常应该提交到 Git。这样团队成员或者部署服务器执行 composer install 时,就可以按照锁定的版本安装,而不是每次都重新寻找最新版本。Composer 官方也明确建议应用项目提交 composer.lock。
至于 vendor/,通常不需要提交到 Git,而是在部署时根据 composer.lock 重新安装。
composer install 和 composer update 千万不要混淆
这是 Composer 最重要的两个命令之一。
如果项目已经存在:
composer.lock
通常应该执行:
composer install
Composer 会按照锁文件安装确定版本。
例如你的开发机器上安装的是:
symfony/console 7.x.x
即使 Packagist 上后来发布了更新版本,只要 composer.lock 没有改变,composer install 仍然会按照锁文件安装原来的版本。
这也是为什么生产服务器部署 PHP 项目时通常使用:
composer install
而不是:
composer update
composer update 的含义完全不同。
它会重新进行依赖解析,在 composer.json 允许的版本范围内寻找新的匹配版本,并更新 composer.lock。
所以开发者应该形成一个很重要的习惯:
开发升级依赖:
composer update
生产部署:
composer install
当然,真实项目还会根据具体情况使用针对单个包的更新,例如:
composer update symfony/console
而不是每次把整个项目的所有依赖全部升级。
版本号里的 ^、~ 和 * 是什么意思
Composer 的版本约束非常重要。
例如:
"symfony/console": "^7.0"
表示允许 Composer 在兼容的 7.x 范围内选择版本。
而:
5.4.*
则明确限制在 5.4 系列。
但不能简单地把所有版本约束都理解成“数字越大越新,所以直接装最新版”。
Composer 必须同时考虑整个依赖树。
假设:
你的项目
↓
A
↓
B
↓
C
A 可能要求:
C >=2.0 <3.0
而你的项目又直接要求:
C ^2.5
Composer 就需要寻找一个能够同时满足这些条件的 C 版本。
如果条件无法同时满足,就会产生依赖冲突。
这也是为什么 Composer 的价值远远超过简单下载工具。它实际上是在解决一个版本约束问题。
Composer 为什么能够自动加载 PHP 类
传统 PHP 项目经常出现这种代码:
require_once 'lib/User.php';
require_once 'lib/Database.php';
require_once 'lib/Helper.php';
项目一大,这种方式很快就会变得难以维护。
Composer 可以生成自动加载器:
vendor/autoload.php
程序通常只需要:
require __DIR__ . '/vendor/autoload.php';
然后就可以使用 Composer 管理的软件包。
例如:
use Symfony\Component\Console\Application;
Composer 会根据软件包提供的自动加载信息寻找对应的 PHP 类。Composer 支持 PSR-4、PSR-0、classmap 等自动加载方式。
更重要的是,你自己的代码也可以使用 Composer 的自动加载。
例如项目结构:
my-project/
├── composer.json
├── vendor/
└── src/
└── User.php
可以在 composer.json 中定义:
{
"autoload": {
"psr-4": {
"App\\": "src/"
}
}
}
修改后运行:
composer dump-autoload
Composer 就会重新生成自动加载映射。
这意味着 Composer 不只是帮你管理第三方代码,也可以成为整个 PHP 项目的代码组织基础。
遇到依赖冲突不要急着删除 composer.lock
很多新手碰到错误时会直接执行:
rm composer.lock
composer update
这种方法有时确实可以重新解析依赖,但不应该成为默认解决方案。
因为删除 composer.lock 后,Composer 可能重新选择大量依赖的版本。原本只是一个小包的问题,最后可能变成整个项目的依赖树发生变化。
更稳妥的做法是先查看:
composer why package/name
或者:
composer why-not package/name 8.0
也可以检查平台环境:
composer show --platform
这些命令能够帮助你判断到底是哪个软件包或者 PHP 扩展限制了版本选择。
如果只是某一个依赖需要升级,更适合针对它进行更新,而不是把整个项目的锁文件推倒重来。
权限问题也不能简单地全部使用 sudo
Linux 环境下执行 Composer 时,有时会看到:
Permission denied
原因可能是项目目录属于其他用户,也可能是之前使用 sudo 执行 Composer,导致 vendor 或 Composer 缓存目录变成了 root 所有。
这时候直接反复使用:
sudo composer install
并不是最好的长期解决办法。
因为你可能因此把项目文件逐渐变成 root 用户所有,下一次普通用户执行 Composer 反而会继续遇到权限问题。
更合理的方法是检查项目目录以及 Composer 缓存的所有者和权限,让运行项目的正确用户拥有相应权限。
在 Web 服务器上尤其需要注意这一点。PHP-FPM、Apache、Nginx 后端用户与 SSH 登录用户可能不是同一个账号,不能只看到“Permission denied”就简单增加权限。
Composer 的安全检查现在应该怎么做
原文中提到的 security-checker 已经不是今天学习 Composer 时应该采用的主要方式。
现在 Composer 自己已经提供了:
composer audit
这个命令可以检查项目依赖中是否存在已知安全漏洞,并且现代 Composer 还能够处理废弃包、恶意软件标记以及相关依赖策略。
因此,新项目可以把:
composer audit
纳入开发和部署流程。
安装或更新依赖时,也可以利用 Composer 当前版本提供的审计和安全策略。
这比过去单独安装一个第三方 security-checker 工具更加符合现在 Composer 的工作方式。
不过安全检查并不意味着“执行一次 audit,以后就安全了”。漏洞数据库会不断变化,软件包也可能停止维护,所以依赖管理本身应该成为持续维护的一部分。
一个 PHP 项目真正使用 Composer 的完整流程
理解 Composer 后,一个比较典型的开发流程其实非常简单。
创建项目:
mkdir my-project
cd my-project
composer init
安装依赖:
composer require symfony/console
开发代码:
require __DIR__ . '/vendor/autoload.php';
修改自己的自动加载配置后:
composer dump-autoload
检查安全问题:
composer audit
升级依赖:
composer update
提交代码时保留:
composer.json
composer.lock
而 vendor/ 通常加入:
.gitignore
部署服务器时:
composer install --no-dev
这样服务器就会按照已经确定的 composer.lock 安装生产环境需要的依赖,而不会因为今天和三个月后的依赖版本不同而产生不可预测的变化。Composer 官方文档也把锁文件与可重复部署作为依赖管理的重要机制。
Composer 最值得理解的地方,其实不是某一条命令,而是它改变了 PHP 项目管理代码的方式。以前一个项目可能需要开发者自己下载类库、寻找依赖、复制文件、维护 require_once,然后担心升级以后哪里会坏掉。Composer 把这些工作变成了一个有规则的依赖系统:composer.json 描述需求,版本约束定义允许的范围,Composer 解析依赖关系,composer.lock 固定结果,vendor 保存实际代码,自动加载器负责把这些代码连接到应用程序中。
当项目规模越来越大时,这套机制的重要性会越来越明显。一个成熟的 PHP 项目并不是“安装了多少个 Composer 包”才显得专业,而是能够清楚知道自己依赖什么、为什么依赖、使用哪个版本,以及升级这些依赖时会发生什么。理解这一点,才算真正开始理解 Composer。
喜欢这篇报道?
使用下面的功能,方便以后继续阅读和分享 MNewsTV
关于文章收藏
收藏不需要注册帐号,收藏信息仅保存在当前浏览器中。
删除收藏请进入「我的收藏」进行管理。
分享 Facebook | X | WhatsApp | LinkedIn
捐助(Paypal): https://www.paypal.me/observeccp 订阅中国观察电报 Telegram : https://t.me/s/ObserveCCP