Laravel 部署需严格匹配 PHP 版本与扩展、正确配置 Web 服务器指向 public 目录并启用重写、确保 .env 在项目根目录且权限合理、执行 config:clear 清缓存、提交 composer.lock 并统一 APP_KEY。

PHP 版本和扩展必须匹配 Laravel 版本
装错 PHP 版本或漏装扩展,composer install 会卡在 laravel/framework 安装阶段,甚至报 Class 'Illuminate\Foundation\Application' not found。Laravel 10 要求 PHP ≥ 8.1,Laravel 11 已要求 PHP ≥ 8.2 —— 不是“能跑就行”,是 composer 会直接拒绝解析依赖。
- 用
php -v确认 CLI 和 FPM(或 Apache mod_php)用的是同一套 PHP,常见坑:CLI 是 8.2,Nginx 走的却是系统默认的 7.4 - 必须启用:
mbstring、openssl、pdo、tokenizer、xml、ctype、json;Laravel Scout 或队列可能还需redis或pcntl - 检查扩展是否真加载:
php -m | grep mbstring比看php.ini更可靠;FPM 用户还要确认php-fpm.conf加载了对应.ini文件
Nginx/Apache 配置要绕过 public/ 入口陷阱
直接把整个 Laravel 项目根目录扔进 /var/www/html 就跑,结果所有请求都 403 或 500 —— 这是因为 Web 服务器必须只暴露 public/ 目录,且需重写规则把非静态资源请求全部转发给 public/index.php。
- Nginx 关键点:
root必须指向/path/to/laravel/public,不是项目根目录;try_files $uri $uri/ /index.php?$query_string缺一不可 - Apache 要确认
.htaccess生效(AllowOverride All),且mod_rewrite已启用;若用 cPanel 或 Plesk,有时需手动开启“重写引擎”开关 - 别在
public/里放.env—— 它必须留在项目根目录(public的上一级),否则APP_KEY读不到,php artisan key:generate也救不回来
Composer 依赖不能只靠本地 install
composer install --no-dev 在服务器上执行失败?大概率是没设好 COMPOSER_MEMORY_LIMIT,或者用了国内镜像但服务器 DNS 解析慢到超时,最终卡在 Downloading https://packagist.org/packages.json。
- 部署前先在本地运行
composer install --no-dev --optimize-autoloader,再把vendor/和bootstrap/autoload.php生成的autoload_classmap.php一起传上去,省去服务器编译环节 - 如果必须在线装,加环境变量:
COMPOSER_MEMORY_LIMIT=-1(防 OOM),COMPOSER_REPO_PACKAGIST=https://packagist.org(避免某些镜像同步延迟导致找不到包) -
composer.lock必须提交进 Git —— 没它,install变成update,版本漂移风险极高;Laravel 10+ 的symfony/polyfill等包对 PHP 小版本敏感,差 0.1 都可能出Declaration of ... must be compatible with ...
APP_KEY 和 .env 不是“配完就完事”
php artisan key:generate 执行成功,但页面还是报 The only supported ciphers are AES-128-CBC and AES-256-CBC?说明 APP_KEY 没生效,或者被缓存覆盖了。
-
.env文件权限必须是 600 或 644,绝不能是 777 —— 否则 Nginx/Apache 可能把它当静态文件直接返回,泄露数据库密码 - 生成
APP_KEY后,立刻清空配置缓存:php artisan config:clear;若已缓存过,config:cache会把旧 key 锁死,光改.env没用 - 多台服务器部署时,
APP_KEY必须一致(比如用 Ansible 变量注入),否则Encrypter解密 session 或 cookie 会失败,用户反复登出
环境变量、文件权限、缓存状态这三者只要漏查一个,.env 就形同虚设。很多人卡在“明明填了 DB_PASSWORD,却连不上数据库”,最后发现是 config:cache 里还存着 DB_PASSWORD=null。











