Menu

PHP Composer:安装包和自动加载类

Composer 是 PHP 的包管理器:composer require vendor/package 把库下载到 vendor/,记录到 composer.json 中,再用 require 'vendor/autoload.php' 加载它。本文讲解如何安装 Composer、composer.json、版本约束、install 与 update 的区别,以及为自己的类配置 PSR-4 自动加载。

本页包含可运行的编辑器。编辑、运行,立即查看输出。

Composer 是 PHP 的包管理器。在项目文件夹中运行 composer require vendor/package:Composer 会把库下载到 vendor/,记录到 composer.json 中,然后你只需一行 require __DIR__ . '/vendor/autoload.php';,就能加载它以及其他所有已安装的包。

composer require monolog/monolog
<?php
require __DIR__ . '/vendor/autoload.php';

use Monolog\Logger;
use Monolog\Handler\StreamHandler;
use Monolog\Level;

$log = new Logger('app');
$log->pushHandler(new StreamHandler(__DIR__ . '/app.log', Level::Warning));
$log->warning('Disk almost full', ['free' => '2%']);

不需要为每个文件写 include:自动加载器会在第一次需要某个类时,加载 Logger、StreamHandler 以及它们用到的所有类。包来自 Packagist,这是 Composer 默认搜索的公共仓库。

安装 Composer

Composer 需要你的电脑上先装好 PHP(参见安装 PHP)。

Windows:从 getcomposer.org 下载并运行 Composer-Setup.exe。它会找到你的 php.exe,并把 composer 添加到 PATH。安装完成后打开一个新的终端。

macOS 使用 Homebrew:

brew install composer

Linux:发行版自带的包(Debian 和 Ubuntu 上是 sudo apt install composer)可以用,但版本往往比较旧。官方安装程序提供的是最新版本:

php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
php composer-setup.php
php -r "unlink('composer-setup.php');"
sudo mv composer.phar /usr/local/bin/composer

getcomposer.org 的下载页面还提供了一行在运行安装程序前校验其哈希值的命令;请从那里复制命令,以获得最新的哈希值。然后检查它能否正常工作:

composer --version

composer.json 和 composer.lock

composer init 会问几个问题,然后写出 composer.json;或者在你第一次 composer require 一个包时自动创建它。一个典型的例子:

{
    "name": "acme/shop",
    "require": {
        "php": ">=8.2",
        "monolog/monolog": "^3.0",
        "vlucas/phpdotenv": "^5.6"
    },
    "require-dev": {
        "phpunit/phpunit": "^11.0"
    },
    "autoload": {
        "psr-4": {
            "App\\": "src/"
        }
    }
}
  • require 列出项目运行所需的依赖,包括 PHP 版本。
  • require-dev 列出只在开发时使用的工具(测试、静态分析)。composer require --dev phpunit/phpunit 会往这里添加,composer install --no-dev 会在生产服务器上跳过它们。
  • autoload 告诉 Composer 你自己的类放在哪里(见下文)。

Composer 还会在旁边写出 composer.lock,记录它安装的每个包的确切版本,包括你的包所依赖的包。两个文件都要提交。不要提交 vendor/:把它加入 .gitignore,因为 composer install 会根据 lock 文件重新生成它。

composer install 与 composer update

composer install          # install exactly what composer.lock says
composer update           # pick the newest allowed versions, rewrite composer.lock
composer update monolog/monolog   # update one package only
composer remove monolog/monolog   # uninstall and remove from composer.json
composer outdated         # list packages with newer versions available

克隆项目后以及每次部署时运行 composer install:每个人都会拿到经过测试的相同版本。只有在打算升级时才运行 composer update,然后测试并提交新的 composer.lock。在生产服务器上运行 update 会安装没有人测试过的版本。

版本约束:^ 和 ~

约束允许的版本适用场景
^3.23.2.0 到 4.0.0(不含)常规选择:获得新功能和修复,不会出现破坏性的主版本
^0.40.4.0 到 0.5.0(不含)1.0 之前的包,次版本也可能有破坏性变更
~3.23.2.0 到 4.0.0(不含)和 ^3.2 相同
~3.2.13.2.1 到 3.3.0(不含)只要修复
3.2.1只允许 3.2.1很少使用,它会挡住安全修复
>=3.2 <3.5自定义范围绕开某个有问题的版本

composer require vendor/package 不写版本时,会选择最新的稳定版本,并为它写入一个 ^ 约束,这通常正是你想要的。

用 PSR-4 自动加载自己的类

PSR-4 是一种把命名空间映射到文件夹的约定:配置 "App\\": "src/" 后,类 App\Text\Slug 就位于 src/Text/Slug.php。添加 autoload 部分后,运行:

composer dump-autoload

Composer 的自动加载器是一个用 spl_autoload_register() 注册的函数,每当代码用到一个尚未加载的类时,PHP 就会调用它。下面的代码块会写出两个类文件,并注册一个自己的小型 PSR-4 自动加载器,让你亲眼看到映射是怎么工作的。试着再添加第三个类文件并使用它。

自动加载器对每个类只运行一次:第二次调用 Slug::from() 时没有输出 autoload: 行,因为这个类已经加载过了。在真实项目中,你永远不需要自己写这个函数;vendor/autoload.php 会注册 Composer 的版本,它还会处理 vendor/ 中的包。命名空间的内容见命名空间页面。

常见错误

  • Class "Monolog\Logger" not found。脚本没有 require 'vendor/autoload.php',或者路径写错了。使用 __DIR__ . '/vendor/autoload.php',这样路径就不会依赖当前目录。
  • 自己的类加入 autoload 后仍然找不到。运行 composer dump-autoload,并检查文件路径是否与命名空间完全一致,包括大小写:App\Text\Slug 必须对应 src/Text/Slug.php,Linux 服务器会把 src/text/slug.php 当成另一个文件。
  • Your requirements could not be resolved to an installable set of packages。两个包需要某个依赖(通常是 PHP 本身)的互不兼容的版本。错误信息会列出冲突;composer why-not vendor/package 2.0 可以解释是什么挡住了某个版本。
  • 系统提示无法识别 composer。终端是在安装之前打开的,或者安装文件夹不在 PATH 中。打开一个新的终端,或者直接调用 php composer.phar。

常见问题

composer install 和 composer update 有什么区别?

composer install 安装的正是 composer.lock 中记录的版本,所以每台机器拿到的代码都一样;克隆项目后和部署时运行它。composer update 会解析 composer.json 允许的最新版本,安装它们并重写 composer.lock;只有在你打算升级时才运行它。

composer.lock 和 vendor 文件夹需要提交吗?

对于应用程序,要提交 composer.lock,这样每个人安装的版本都相同。不要提交 vendor/:把它加入 .gitignore,让 composer install 重新生成它。

composer.json 中的 ^ 是什么意思?

^2.3 允许从 2.3.0 到 3.0.0(不含)之间的任何版本:可以获得新功能和修复,但不会升级到可能破坏代码的新主版本。~2.3 的含义相同,而 ~2.3.1 只允许 2.3.1 起的 2.3.x 版本。

怎么用 Composer 自动加载自己的类?

在 composer.json 中添加 "autoload": {"psr-4": {"App\\": "src/"}},运行 composer dump-autoload,然后 require 'vendor/autoload.php'。之后第一次使用类 App\Mail\Mailer 时,它会从 src/Mail/Mailer.php 加载。

怎么查看安装的 Composer 版本?

运行 composer --version。要升级 Composer 本身,运行 composer self-update,或者通过当初安装它的包管理器升级,例如 brew upgrade composer。

Coddy 编程语言插图

和 Coddy 一起学编程

开始