数据库配置不应硬编码,须通过环境变量(如env::get)动态加载并url编码敏感字段,校验缺失凭证,且.env文件严禁提交和自动部署。

数据库配置不能写死在 database.php
硬编码账号密码到配置文件里,等于把钥匙钉在门框上——Git 提交、CI/CD、多人协作时一抓一个准。ThinkPHP 默认的 database.php 是 PHP 文件,直接 return 数组,执行即暴露凭证。
正确做法是让配置从环境变量或独立配置文件加载,运行时注入:
- 用
$_ENV或getenv()读取环境变量(推荐),例如DB_USERNAME、DB_PASSWORD - 把敏感字段从
database.php中移出,改用Env::get('database.username')动态获取 - 确保
.env文件不在 Git 跟踪范围内(加进.gitignore),且不随部署包下发到生产机
ThinkPHP 6+ 的 .env 加载时机很关键
ThinkPHP 在容器初始化前就加载了 .env,但如果你手动调用 Env::get() 太早(比如在 common.php 或扩展初始化中),可能读不到值——因为 think\facade\Env 还没准备好。
安全的使用位置只有两个:
- 配置文件中(如
config/database.php):它被框架自动 require,此时Env已就绪 - 控制器、中间件、命令行类等运行时上下文里:只要不是在
bootstrap阶段提前执行,都 OK
别在 provider 类的 register() 方法里直接读 Env::get('db.password'),容易空值——改用延迟解析或依赖注入。
database.php 中动态拼接 DSN 的坑
MySQL 的 DSN 字符串对特殊字符(如 @、/、:)敏感,直接拼接 mysql:host=...;dbname=... 会因密码含 @ 导致解析错乱,报错 SQLSTATE[HY000] [1045] Access denied。
必须对敏感字段做 URL 编码:
- 用
rawurlencode($username)和rawurlencode($password)处理账号密码 - 不要用
urlencode(),它把空格转成+,而 DSN 要求空格必须是%20 - ThinkPHP 自带的
Connection类不自动编码,得自己在配置数组里处理好再传进去
示例片段:
'dsn' => 'mysql:host=' . Env::get('database.host') . ';dbname=' . Env::get('database.database') . ';charset=' . Env::get('database.charset'),
'username' => rawurlencode(Env::get('database.username')),
'password' => rawurlencode(Env::get('database.password'))
多环境部署时,.env 容易被覆盖或遗漏
上线脚本如果用 cp .env.example .env,或者 CI/CD 流水线没注入真实凭证,就会沿用默认测试值,导致线上连错库甚至连到测试库。
防御性做法:
- 在
config/database.php开头加校验:if (!Env::get('database.username')) { throw new Exception('DB credentials missing in .env'); } - 部署后跑一次
php think run或健康检查接口,主动触发连接,早暴雷 - 禁止任何自动化流程生成
.env,所有环境的凭证由运维单独注入(Ansible vault / K8s Secret / 云参数仓库)
最麻烦的不是配不好,而是配错了还悄无声息跑着——尤其跨环境复用代码时,.env 差一个字符,连的就是另一套数据。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!










