接手一个老项目,最头疼的事之一就是给它塞进 Composer 的依赖管理。直接一个 composer init 敲下去,看起来省事,但生成的 autoload 配置大概率跟你的目录结构对不上——等跑起来摔个 Class not found,又得从头排查。其实有个更稳妥的路径:先手动搭一个最精简的 composer.json,清掉自动加载字段,跑一遍 composer install 验证基础框架,然后再根据真实的文件位置来配 classmap 或 files,最后通过 composer dump-autoload 让它生效。下面把每一步拆开说,踩过的坑也一并列出来。

直接在老项目里跑 composer init 很容易生成错的 autoload 配置,导致后续 Class not found;正确路径是先手动建最小 composer.json,再按真实目录结构配 classmap 或 files,最后才引入 vendor/autoload.php。
怎么初始化 composer.json 而不踩坑
别用交互式 composer init——它默认把 src/ 当 PSR-4 根目录,但你的类可能全在 includes/ 或 lib/ 里,填错一步后面全得重来。
- 进项目根目录,运行
composer init --no-interaction,跳过所有提问,生成基础文件 - 立刻编辑刚生成的
composer.json,清空"autoload"字段(留空或删掉整段),先不配任何自动加载 - 确认当前有没有已存在的
vendor/autoload.php(比如之前零散装过包),如果有,先别删,留着过渡用 - 运行
composer install,验证是否能无报错完成——此时应没新文件写入、也没警告
autoload 怎么配才对老代码生效
Class not found 报错里,90% 是因为 autoload 配置和实际文件位置对不上。Composer 不猜路径,只认你写的映射。
- 老项目没命名空间、类文件叫
User.class.php或Db.php?用"classmap": ["includes/", "lib/"],然后跑composer dump-autoload - 有全局函数文件(如
helpers.php)?必须写成"files": ["./helpers.php"],相对路径要加./前缀,否则vendor/autoload.php加载时找不到 - 别混用
psr-4和classmap指向同一目录,会覆盖或冲突;不确定就只用classmap,它最实在 - 改完
composer.json的autoload段,必须立刻执行composer dump-autoload,否则新配置不生效
入口文件怎么安全引入 vendor/autoload.php
不能随便在某个 include 后面加 require 'vendor/autoload.php'——老项目常在开头就定义 __autoload() 或手动 require 一堆类,顺序一错就是 fatal error。
- 只在真实入口文件顶部加(
index.php、api.php、CLI 脚本),且必须放在所有require/include之前 - 加之前检查是否已有
__autoload():如果存在,先用spl_autoload_unregister('__autoload')卸载,避免和 Composer 加载器冲突 - 别在
config.php或functions.php里require它——这类文件常被多处包含,会引发重复加载或作用域污染 - 确保
vendor/autoload.php存在:加个if (file_exists(__DIR__ . '/vendor/autoload.php')) { require __DIR__ . '/vendor/autoload.php'; }更稳妥
require 和 require-dev 怎么分才不线上崩
老项目常把 phpunit 放生产环境,或漏掉 monolog/monolog 这种实际被 index.php 调用的日志依赖——判断依据不是“我写代码时用不用”,而是“这个类会不会被线上 PHP 进程执行”。
require:所有会被入口文件、定时任务、API 控制器直接调用的包,例如guzzlehttp/guzzle、doctrine/dbal、monolog/monologrequire-dev:只在本地开发或 CI 中跑的工具,例如phpunit/phpunit、roa ve/security-advisories、php-cs-fixer- 不确定时先放
require-dev,上线前用grep -r "use.*Monolog\|new.*Logger" .扫一遍代码,确认有调用再挪到require - 升级前务必检查
composer.json里的"php"版本约束是否匹配当前php -v输出,不匹配就先改约束,别让composer update自己跳版本
最关键的细节是:每次改完 autoload 配置或新增 files,必须手动跑 composer dump-autoload;这个步骤没法省,也看不出明显反馈,但漏了就一定加载失败。