.env文件只该存开发默认值,生产密钥必须通过web服务器环境变量注入,否则database_url为空、app_secret泄露、.env.prod.local根本不加载;因.env默认未被gitignore,提交即导致密码暴露,且app_env须由web服务器(如apache setenv或nginx fastcgi_param)预设,否则loadenv()不加载.env.prod*文件。

直接说结论:.env 文件只该存开发默认值,生产密钥必须通过 Web 服务器环境变量注入,否则 DATABASE_URL 空、APP_SECRET 泄露、.env.prod.local 根本不加载。
为什么 .env 文件不能写生产密码
因为 .env 默认在 Git 里没被忽略,一旦提交,数据库密码、API 密钥全暴露。Symfony 官方明确要求:.env 只放开发用的占位值(如 DATABASE_URL="mysql://root:password@127.0.0.1:3306/symfony"),真实密码必须进 .env.prod.local,且该文件必须加进 .gitignore。
常见错误现象:bin/console debug:container --env-var=DATABASE_URL 显示未定义,但 .env.prod.local 文件明明存在。
- 检查
APP_ENV是否已由 Web 服务器预设(Apache 用SetEnv APP_ENV prod,Nginx 用fastcgi_param APP_ENV prod) - CLI 下运行
echo $APP_ENV验证——如果为空,loadEnv()根本不会加载.env.prod*类文件 -
.env.prod.local里不能有语法错误,比如漏引号、${DB_HOST}没闭合、@或/没 URL 编码
DATABASE_URL 怎么写才真正能连上 MySQL
错一个字符就报 SQLSTATE[HY000] [2002] No such file or directory 或 Access denied。关键点不是 Doctrine 配置,而是 URL 本身合法且可连通。
- 协议头必须是
mysql://,不能省略 - 主机写
127.0.0.1,别写localhost(否则 MySQL 尝试走 socket,报错 No such file) - 密码含
@、/、:必须 URL 编码:如pass@word→pass%40word,my/pwd→my%2Fpwd - 显式声明
serverVersion:MySQL 8.0 写?serverVersion=8.0,否则 Doctrine 生成的 SQL 可能不兼容 - 推荐加上
&charset=utf8mb4,避免 emoji 和四字节中文存不进库
正确示例:DATABASE_URL="mysql://root:my%40pass@127.0.0.1:3306/symfony?serverVersion=8.0&charset=utf8mb4"
%env(resolve:DB)% 和 %env(DB)% 的区别在哪
直接写 %env(DB)% 是纯字符串替换,而 %env(resolve:DB)% 才会真正解析变量、执行默认值、调外部命令。很多配置失效,就是因为用了前者。
-
%env(DB)%:把DB环境变量原样塞进字符串,不处理嵌套引用(如${DB_HOST})、不展开$(date)、不支持类型转换 -
%env(resolve:DB)%:先解析${DB_PORT:-3306},再执行$(aws secretsmanager get-secret-value...),最后才注入;%env(int:MAX_RETRY)%这类也必须带resolve - 性能注意:
resolve每次请求都重新解析,生产环境务必配合bin/console dotenv:dump编译成.env.local.php,否则拖慢响应
APP_ENV 和 APP_DEBUG 别在 .env 里硬编码
很多人在 .env 里写 APP_ENV=prod,这是反模式。它会导致本地调试时误用生产配置,且无法区分不同部署目标(如 staging 和 prod)。
正确做法是:让服务器控制环境变量。
- Apache 虚拟主机中加:
SetEnv APP_ENV prod、SetEnv APP_SECRET your_real_secret_here - Nginx 的
location ~ ^/index\.php(/|$)块里加:fastcgi_param APP_ENV prod;、fastcgi_param APP_SECRET ...; -
.env文件里只保留APP_ENV=dev和APP_DEBUG=1——仅用于本地开发兜底
最易被忽略的一点:环境变量一旦由 Web 服务器设置,.env 里的同名变量就完全被跳过,连加载都不加载。所以别指望改 .env 能切环境。











