改了 .env 但 config() 仍是旧值,因 Laravel 启动时一次性加载环境变量,后续不重读;需重启服务或运行 php artisan config:clear 更新。

为什么 .env 文件改了但 config() 还是旧值
Laravel 在启动时会把 .env 里的变量一次性加载进 PHP 的 $_ENV 和 getenv(),之后就不再读取文件。所以改完 .env 不重启服务或清缓存,config('app.name') 这类调用不会更新。
- 开发环境:改完
.env后必须运行php artisan config:clear(或php artisan config:cache,但后者只适合生产) - 生产环境:不能依赖
.env,应直接通过系统级环境变量设置(如 Nginx 的fastcgi_param或 systemd 的Environment=) - 常见误操作:在
config/app.php里写env('APP_NAME', 'Laravel')—— 这个没问题;但如果在中间件、命令或模型里直接调用env('FOO'),部署后可能返回null(因为config:cache会移除所有env()调用)
env() 和 config() 到底该用哪个
env() 只应在配置文件(config/*.php)中使用,且仅用于给 config() 提供默认值;业务代码里一律用 config() 或 Config::get(),否则缓存后失效。
-
env('DB_HOST')✅ 可以出现在config/database.php里 -
env('DB_HOST')❌ 出现在控制器或命令里 → 缓存后返回null - 想动态读取环境变量?用
$_SERVER['DB_HOST']或getenv('DB_HOST')(但需确保没被config:cache干扰) - 敏感值(如 API 密钥)别硬编码在配置文件里,哪怕用了
env()—— 确保.env不提交到 Git,且权限为600
Laravel 9+ 的 APP_URL 和 HTTPS 自动识别问题
当 Laravel 部署在反向代理(Nginx / Cloudflare)后面时,APP_URL 写成 http:// 会导致生成的 URL 错误,而单纯改成 https:// 又会让本地开发报错。
- 正确做法:删掉
APP_URL,让 Laravel 根据请求头自动推导(需确保代理转发了X-Forwarded-Proto) - 如果必须设
APP_URL,用{scheme}://example.com格式 → Laravel 会自动替换{scheme}为http或https - 关键配置:在
AppServiceProvider::boot()加上URL::forceScheme('https')(仅限全站 HTTPS),或更稳妥地用TrustProxies中间件配置$proxies和$headers - 验证方式:打印
url('/')和request()->fullUrl()对比协议是否一致
多环境部署时 .env 文件怎么管理
没有“一套 .env 打天下”的方案。不同环境(本地/测试/预发/生产)的数据库、缓存、队列配置必然不同,靠手动改容易出错。
- 推荐做法:用
.env.example作为模板,每个环境单独维护一份.env(不进 Git),配合部署脚本注入变量(如 Ansible 的lineinfile或 Docker 的--env-file) - 禁止做法:把
.env.production提交到仓库,再靠cp .env.production .env切换 —— 容易漏改、覆盖、权限错误 - CI/CD 场景:用平台提供的 secret 功能(GitHub Actions 的
secrets,GitLab CI 的variables),在部署时写入.env - 注意:Laravel 不支持
.env.local或自动加载多个 env 文件,别试图用vlucas/phpdotenv手动加载额外文件,会和框架冲突
环境变量不是“写进去就完事”,它串起了配置加载、缓存机制、代理识别和部署流程。最容易被忽略的是:缓存配置后 env() 失效、反向代理没传头导致 URL 协议错乱、以及把 .env 当配置中心去动态修改。










