答案是本地构建完整 vendor 目录再上传。需用与主机一致的 PHP 版本执行 composer install --no-dev --optimize-autoloader,确认 autoload.php 有效后上传整个 vendor(含隐藏文件),并修正入口路径、权限及 autoload 配置。

composer install 在共享主机上直接执行失败,怎么办?
绝大多数共享主机(cPanel、SiteGround、Bluehost 等)默认禁用 exec()、proc_open() 或根本没装 Composer 二进制,导致上传 composer.json 后直接运行 composer install 报 command not found 或 proc_open() has been disabled。这不是配置问题,是主机策略限制——你无法在服务器上“运行 Composer”,只能绕过它。
实操建议:
- 本地用和目标主机**完全一致的 PHP 版本**(比如主机是 PHP 8.1.12,你就别用 8.2 开发)执行:
composer install --no-dev --optimize-autoloader - 确认
vendor/autoload.php能正常加载:写个test-autoloader.php,内容为<?php require 'vendor/autoload.php'; echo "OK"; ?>,本地访问测试 - 上传整个
vendor/目录(含隐藏文件如.htaccess),不要只传部分或忽略vendor/composer/下的autoload_classmap.php等生成文件 - 检查文件权限:共享主机通常要求
vendor/和子目录为755,PHP 文件为644;若报Permission denied,优先用 FTP 客户端批量修复,而非依赖chmod命令(多数不支持)
上传 vendor 后 Class not found,但文件明明存在
常见于路径错位或 autoloader 未触发——尤其当项目结构非标准(如 Laravel 不在根目录、public 入口被重命名)时。vendor/autoload.php 是相对路径加载器,默认假设入口脚本与 vendor/ 同级。一旦层级变动,就会失效。
实操建议:
- 在入口文件(如
index.php)顶部加一行:define('COMPOSER_VENDOR_DIR', __DIR__ . '/../vendor');,再显式引入:require COMPOSER_VENDOR_DIR . '/autoload.php'; - 避免用
../vendor/autoload.php这类硬编码路径;改用dirname(__DIR__) . '/vendor/autoload.php'更健壮 - 检查
composer.json中的autoload配置是否含自定义psr-4映射,且对应目录已随代码上传(例如"App\": "app/",就要确认app/目录存在) - 若用 Laravel,确保
bootstrap/autoload.php(旧版)或bootstrap/app.php(新版)中require的路径指向正确位置,不是默认的vendor/autoload.php
本地构建后 vendor 体积过大,上传超时或失败
共享主机常对单次上传大小、FTP 连接时长设限(如 SiteGround 限 200MB,GoDaddy 限 50MB)。vendor/ 动辄 100MB+,尤其含 symfony/*、laravel/framework 等大包时极易卡住。
实操建议:
- 用
--prefer-dist(默认开启)而非--prefer-source,跳过 Git 元数据,减小 ZIP 包体积 - 删掉无用文档和测试文件:在
composer.json的extra字段加"archive": {"exclude": ["/docs", "/tests", "/Tests", "/README.md", "/CHANGELOG.md"]},再运行composer install - 上传前压缩为
vendor.tar.gz,再通过主机后台的「文件管理器」解压(比 FTP 上传更稳定);注意解压后检查文件权限是否重置 - 若主机支持 SSH 且开放
tar命令,可上传压缩包后执行:tar -xzf vendor.tar.gz -C /path/to/webroot,避免分片传输中断
CI 构建产物复用 vendor 失效,每次都要重装
CI 流水线(如 GitHub Actions)里用 composer install 每次都从零拉包,慢且易因网络波动失败。你以为加了缓存就稳了?其实 Composer 缓存只存下载的 ZIP,不存最终 vendor/ 结构;且 composer.lock 变更、PHP 版本微调都会让缓存失效。
实操建议:
- 用
actions/cache@v3缓存~/.composer/cache,但必须把composer.lock的 hash + PHP 版本号作为 key,例如:key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}-${{ env.PHP_VERSION }} - 更可靠的做法是:构建阶段用多阶段 Dockerfile,第一阶段
FROM composer:2安装依赖,第二阶段FROM php:8.1-apache复制/app/vendor,彻底规避运行时网络依赖 - 若必须上传
vendor/到对象存储(如 S3),记得同步上传composer.lock并校验 checksum,否则下次composer install --no-install无法验证一致性 - 警惕 CI 环境时间偏差:GitHub Actions 启动快,NTP 可能未同步就跑
composer install,导致 signature verification failed;开头加sleep 2 && timedatectl timesync-status --wait
最常被忽略的一点:共享主机的 opcache.restrict_api 或 disable_functions 可能拦截 file_get_contents(),导致 autoload_static.php 加载失败——这时错误不会明说,只会静默跳过类注册。务必用 phpinfo() 查看这两项配置,而非只盯着 Class not found 日志。


















