“Class not found”报错的根源常是vendor目录属主错误或PSR-4路径大小写不一致:前者因CI构建用户与Web运行用户(如www-data)不匹配,导致autoload.php或classmap.php不可读;后者因Mac开发环境不区分大小写,而Linux生产环境严格区分,使autoload_psr4.php中路径与实际目录名大小写不符。

报错提示“Class not found”但文件存在,先查 autoload.php 所在目录归属
这类问题在 CI/CD 构建后直接 rsync 到生产机、或 Docker 多阶段构建中很常见。错误本身不指向权限,但根本原因是 vendor/autoload.php 或其父目录(如 vendor/)属主不是运行 PHP 的用户。比如 Web 服务用 www-data,而构建时是 jenkins 用户生成的 vendor,就会导致加载失败。
直接检查:ls -ld vendor/ vendor/autoload.php。如果输出里第三列(属主)不是当前 Web 用户(www-data 或你实际使用的用户),就是它了。
- 不要用
chmod -R 775 vendor/—— 这不能解决属主错位,反而可能让可执行脚本(如vendor/bin/phpunit)被安全扫描器拦截 - 修复方式是重置归属:
sudo chown -R www-data:www-data vendor/(假设 Web 用户是www-data) - 如果 vendor 是构建阶段生成的,建议构建完成后立刻
chown,而不是等部署后再修
CI 构建机器与生产机用户不一致,导致 classmap.php 写入失败或读取异常
当 CI 使用 root 或 gitlab-runner 用户执行 composer install --no-dev --optimize,生成的 vendor/composer/autoload_classmap.php 文件就归那个用户所有。若生产机上 PHP-FPM 以 www-data 运行,它可能无权读取该文件(尤其当 umask 严格时),表现为类加载时静默失败或报 include(): Failed opening。
验证方法:sudo -u www-data cat vendor/composer/autoload_classmap.php 2>/dev/null || echo "read denied"。
- 构建阶段应显式指定运行用户:
sudo -u www-data composer install --no-dev --optimize(需提前配置好该用户有写权限) - 更稳妥的做法:构建完立即修正归属:
sudo chown -R www-data:www-data vendor/ - 避免使用
--classmap-authoritative后还让多个进程并发写 vendor —— 它要求 classmap.php 完整且只读;若部署脚本没加锁,两个 worker 同时 reload 可能导致文件被截断
多 Worker 进程共享 vendor 目录时,autoload.php 被并发修改引发加载冲突
在 Swoole、Workerman 或 PHP-FPM 多 worker 场景下,如果部署流程里包含 composer dump-autoload 或 composer install,多个进程可能同时尝试写 vendor/autoload.php 或 autoload_static.php,造成文件内容损坏或中间态残留。现象是偶发性 Fatal error: Cannot declare class X 或类定义不一致。
这不是 Composer bug,而是部署方式违反了“构建与运行分离”原则。
- 禁止在运行中的生产环境执行任何
composer命令 —— vendor 必须是构建阶段完全生成、不可变的 - 构建产物应包含完整 vendor + 生成好的
autoload_static.php(用composer dump-autoload --static) - 若必须动态加载,改用
--apcu或外部缓存,而非依赖文件系统上的 autoload 文件
Linux 系统大小写敏感 + Mac 开发环境混合导致 autoload_psr4.php 路径错乱
开发在 Mac 上用 app/models/User.php,但 composer.json 写的是 "App\": "app/Models/"。Mac 默认不区分大小写,所以本地能跑;但部署到 Linux 后,autoload_psr4.php 里记录的路径仍是小写的 app/models/,而 PSR-4 加载器按命名空间拼出 app/Models/User.php,最终找不到文件。
关键线索:报错路径和真实文件路径仅差大小写,且只在 Linux 生产环境复现。
- 检查
vendor/composer/autoload_psr4.php中对应命名空间的路径字符串是否全小写 - 统一规范:目录名用 PascalCase(
Models、Services),文件名首字母大写(User.php),命名空间严格匹配 - CI 流程中加入校验脚本:
find app/ -name "*.php" -exec basename {} ; | grep -v "^[A-Z]",提前暴露小写文件名


















