laravel环境变量生效需满足三条件:.env文件存在、app_env值合法(如local/staging/production)、配置缓存已清除;改.env后config()仍旧值,主因是未运行php artisan config:clear,或已执行config:cache导致env()调用被固化。

直接说结论: Laravel 的环境变量不是靠“设置”出来的,而是靠 .env 文件 + APP_ENV 值 + 配置加载时机三者共同决定的;你改了 .env 却没生效,90% 是因为缓存没清、APP_ENV 不合法,或在错误位置调用了 env()。
为什么改了 .env 但 config('app.debug') 还是 false?
这是最常踩的坑:Laravel 启动时只解析一次 .env,之后所有配置都来自 config/*.php 中的 env() 调用结果。一旦运行过 php artisan config:cache,这些 env() 就被求值固化进 bootstrap/cache/config.php,后续再改 .env 完全无效。
- 验证是否已缓存:检查
bootstrap/cache/config.php是否存在且非空 - 必须先执行
php artisan config:clear,再改.env,最后重新config:cache - 如果在
tinker里执行env('APP_DEBUG')返回null,说明缓存已启用且env()函数本身被 Laravel 禁用了(Laravel 9+ 默认行为) - 开发中建议禁用
config:cache,只在部署前启用
APP_ENV=local 和 APP_ENV=production 有什么实际区别?
它不只影响日志级别或调试开关,更关键的是控制 Dotenv 加载逻辑:APP_ENV 必须是 Laravel 认可的值(如 local、staging、production),否则 .env 根本不会被加载 —— 即使文件存在,env('DB_HOST') 也会返回 null。
- 常见非法值:
dev、development、test(Laravel 不识别,.env被跳过) - 合法值见
Illuminate/Foundation/Bootstrap/LoadEnvironmentVariables.php源码,核心是in_array($app->environment(), ['local', 'staging', 'production']) - 修改
APP_ENV后,必须重启 PHP-FPM 或 Web 服务器(如 Nginx)才能让$_SERVER['APP_ENV']生效 - 不建议用
.env.production这类多文件机制,Laravel 默认只读.env;多环境应靠 CI/CD 注入或服务器级环境变量覆盖
为什么不能在控制器里直接写 env('API_KEY')?
因为 env() 只在应用启动时有效,且仅用于配置加载阶段。把它塞进控制器、中间件或命令里,等于在缓存已生成、Dotenv 已卸载后强行调用一个被禁用的函数 —— 在生产环境必然返回 null,且无法 fallback。
- 正确路径:在
config/services.php里定义'api_key' => env('API_KEY', ''),然后在代码中用config('services.api_key') - 敏感值(如数据库密码)不要设默认值,留空即可,避免误用默认值连错库
- 需要类型转换的变量(如布尔、整数),务必在 config 文件里处理:
filter_var(env('APP_DEBUG', false), FILTER_VALIDATE_BOOLEAN) - 前端要用的变量,必须加
MIX_前缀(如MIX_API_URL),否则 Laravel Mix 不会注入到 JS 中
部署时如何安全注入环境变量?
把 .env 文件上传到服务器是最不推荐的做法。真正安全的方式是绕过 .env,直接向 PHP 进程注入环境变量,让 env() 在启动时就读到真实值。
- PHP-FPM 方式:在
www.conf里写env[DB_PASSWORD] = "real_secret" - 系统级方式:在
/etc/profile或 systemd service 文件中export DB_PASSWORD="xxx" - Docker 方式:用
docker run -e DB_PASSWORD=xxx或env_file:指定外部 env 文件 - CI/CD 流程中,必须确保环境变量注入步骤发生在
php artisan config:cache之前,否则白搭
最易被忽略的一点:哪怕你用服务器环境变量覆盖了所有值,只要 .env 文件还躺在项目根目录下,它就仍可能被 Web 服务器意外暴露(比如 Nginx 配置漏了 location ~ /\.env { deny all; })。删掉它,或至少确保 Web 层彻底屏蔽访问。











