Laravel修改.env后不生效,主因是配置被缓存:执行php artisan config:clear清除bootstrap/cache/config.php缓存文件后,框架才会重新读取.env;若仍无效,需检查.env格式错误、BOM头、系统环境变量覆盖或PHP-FPM/Docker连接池未重启。

改了 .env 里的数据库配置却还是连旧库,不是配置没生效,而是 Laravel 没“看到”新值——它在启动时读取的是缓存的配置,不是实时解析的 .env。
为什么改了 .env 却不生效
Laravel 启动时会把所有 config/* 文件(包括 config/database.php)合并后写入 bootstrap/cache/config.php。这个缓存文件一旦存在,框架就跳过 .env 解析,直接用缓存里的值。所以你改了 DB_HOST 或 DB_DATABASE,只要没清缓存,它永远读不到。
-
php artisan config:clear是必须步骤,不是可选操作 - 如果项目跑在 Apache + mod_php 模式下,且 PHP 是线程安全(TS)版本,
getenv()和putenv()可能被多个请求污染,导致部分请求读到旧环境变量(尤其多项目共用一个 PHP 进程时) -
.env文件末尾有不可见空格、BOM 头,或某行用了中文等号(=),都会让env('DB_HOST')返回null,最终 fallback 到config/database.php里的默认值(比如'127.0.0.1')
怎么确认是不是缓存问题
运行这条命令看当前实际加载的数据库配置:
php artisan tinker --execute="dd(config('database.connections.mysql'))"
输出里 host、database 等字段显示的值,就是 Laravel 正在用的——它和你的 .env 一致吗?不一致,说明缓存没清;一致但连接仍错,问题在别处。
- 检查输出中
host是不是null:如果是,大概率是.env格式错误或 BOM 头干扰 - 检查
driver是否为mysql:若显示sqlite,说明DB_CONNECTION拼错了或被其他配置覆盖 - 别只信
php artisan migrate:status的结果——它可能连上的是另一个库(比如本地有两个 Laravel 项目,Apache prefork 模式下共享了环境变量)
连上了但还是旧数据?可能是连接池没刷新
这常见于生产环境或 Docker 部署:PHP-FPM 进程常驻,数据库连接池(如 PDO 连接)在进程启动时就建好了。即使你改了 .env 并清了配置缓存,已建立的连接不会自动断开重连。
- 重启 PHP-FPM 或 Apache/Nginx 才能让新配置真正落地到每个工作进程中
- Docker 环境下,仅
docker-compose restart app不够,要确保app容器重建(docker-compose up -d --force-recreate app),否则旧镜像里的进程还在用旧连接 - 如果用的是 Swoole 或 Octane,它们的连接池生命周期更长,必须
php artisan octane:reload或完整重启服务
最常被忽略的一点:清完缓存后,别只测 php artisan migrate,而要用真实请求触发数据库操作(比如访问一个 Eloquent 查询的页面),因为 Artisan 命令有时会走独立配置加载路径,掩盖了 Web 请求下的真实问题。


















