php数据库配置须分离敏感信息:config/database.php仅留骨架,用$_env读取db_host等变量,禁硬编码;.env文件需utf-8无bom、被dotenv加载且不提交;生产环境用系统级环境变量,校验host/dbname/username非空及host为内网ip,避免localhost歧义。

PHP数据库配置文件不能直接写密码进代码,也不能靠改注释切换环境——这样上线就炸。
config/database.php 里只留骨架,敏感值全走 $_ENV
配置文件本身要干净、可提交、无密码。比如 config/database.php 应该长这样:
return [
'host' => $_ENV['DB_HOST'] ?? '127.0.0.1',
'port' => (int)($_ENV['DB_PORT'] ?? 3306),
'dbname' => $_ENV['DB_NAME'] ?? '',
'username' => $_ENV['DB_USER'] ?? '',
'password' => $_ENV['DB_PASS'] ?? '',
'charset' => 'utf8mb4',
'options' => [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_EMULATE_PREPARES => false,
],
];
- 所有敏感字段都用
$_ENV读取,不硬编码、不 fallback 到明文密码 -
?? ''是为了防止未定义时报 Notice,但空字符串在连接时会立刻失败,比静默错更好定位 - 端口强制转
(int),避免字符串传入 PDO 导致连接被拒绝(某些 PHP 版本对 port 类型敏感) - 不要在配置里拼 DSN 字符串,留到 PDO 构造时再拼,便于调试和复用
本地用 .env,生产用系统环境变量
开发时靠 .env 文件注入,但必须满足三个条件才真正生效:
-
.env文件在项目根目录,且编码为 UTF-8 无 BOM - 启动前已调用
Dotenv\Dotenv::createImmutable(__DIR__)->load();(或框架已内置) - Web 服务器(如 Nginx)或 CLI 启动脚本中,没有同名系统变量覆盖 —— 环境变量优先级是:系统变量 >
.env> 默认值
生产环境禁止放 .env 文件。运维应在服务器级设置:
export DB_HOST=10.10.20.5 export DB_NAME=prod_app export DB_USER=app_rw # DB_PASS 存在密钥管理服务或由 systemd env 文件注入,不进 shell 历史
验证是否生效:php -r "var_dump($_ENV['DB_HOST']);",不是 getenv(),因为部分 SAPI 下 getenv 不一定同步更新。
别信 localhost,127.0.0.1 才是稳定选择
MySQL 默认开启 skip_name_resolve(phpEnv、Docker 镜像普遍开),此时 localhost 会走 Unix socket,而 127.0.0.1 强制走 TCP。两者行为不一致,极易导致本地能连、部署后连不上。
- 统一在配置中写
127.0.0.1,除非你明确需要 socket 连接(如性能敏感且同机部署) - 检查 MySQL 实际监听:
mysql -u root -e "SHOW VARIABLES LIKE 'bind_address';" - 如果 MySQL 配置了
bind_address = ::1(IPv6 only),PHP 用127.0.0.1就会超时,得改成::1或放开 IPv4
加载后必须校验,不能等 PDO 报错才发现
PDO 连接失败时抛出的异常信息往往模糊(比如 “SQLSTATE[HY000] [2002] No such file or directory”),其实只是 host 写成了 localhost 而 MySQL 没开 socket。更早拦截能省掉一半排查时间。
- 在配置加载后、PDO 初始化前,加一段显式校验:
if (empty($config['host']) || empty($config['dbname']) || empty($config['username'])) {
error_log('Database config missing required keys: host/dbname/username');
die('Database configuration incomplete');
}
- 生产环境额外校验
$config['host']是否为内网地址(正则匹配^10\.|^172\.(1[6-9]|2[0-9]|3[0-1])\.|^192\.168\.),防误配成公网 IP - 别把整个
$config丢进error_log()—— 密码可能还在$_ENV里没清,日志文件就成了泄露源
最常被跳过的其实是环境变量加载顺序和校验时机:.env 加载了,但框架缓存了旧配置;或者校验写了,却放在 PDO 实例化之后——这时候错误已经发生,校验形同虚设。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











