mysqli_connect()四个参数顺序必须为host、user、password、dbname,端口须作为第五参数显式传入,否则默认连3306;localhost与127.0.0.1行为不同,前者走socket后者走tcp;空密码须传空字符串""而非null。

mysqli_connect() 的四个参数顺序不能错
PHP7.3 中用 mysqli_connect() 建连,必须按 host、user、password、dbname 顺序传参。端口不能直接写在 host 字符串里(如 "localhost:3308")就完事——它只在面向对象方式或 DSN 中被原生识别;而面向过程调用时,端口必须作为第五个参数显式传入,否则会被忽略。
常见错误现象:mysqli_connect(): (HY000/2002): Connection refused,表面是连不上,实际常因端口没传导致连了默认 3306,但服务其实在 3308。
- 正确写法(显式端口):
$conn = mysqli_connect($host, $user, $password, $dbname, $port); - 错误写法(仅字符串拼端口):
$conn = mysqli_connect("localhost:3308", $user, $password, $dbname);→ 这会尝试连localhost:3308,但部分 PHP 构建版本不解析该格式,尤其在 Alpine 或某些 Docker 环境中失效 - 若端口固定且不想每次传,改用面向对象方式更稳妥:
new mysqli($host, $user, $password, $dbname, $port)
PDO 连接字符串里 charset 必须写在 DSN 内部
用 PDO 时,charset=utf8mb4 必须塞进 DSN 字符串里,比如 "mysql:host=localhost;dbname=test;charset=utf8mb4"。如果只在 options 数组里设 PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8mb4",或靠 set_charset() 补救,都可能晚于建连阶段,导致中文存成问号或报错 Incorrect string value。
性能影响:不声明 charset 在 DSN 中,PDO 会先以服务器默认字符集(可能是 latin1)握手,再执行 SET NAMES,多一次往返,高并发下可测出毫秒级延迟差异。
- 推荐写法:
new PDO("mysql:host=$host;dbname=$dbname;charset=utf8mb4", $user, $pass, [...]) - 避免写法:
"mysql:host=$host;dbname=$dbname"+ 单独调$pdo->exec("SET NAMES utf8mb4") - 注意:
utf8mb4不要写成utf-8或utf8(MySQL 中utf8实为utf8mb3,不支持 emoji)
host 值选 localhost 还是 127.0.0.1?取决于 MySQL 的 bind-address
PHP7.3 脚本里写 $host = "localhost" 和 $host = "127.0.0.1" 行为完全不同:前者走 Unix socket(如果 MySQL 配置允许),后者强制走 TCP/IP。一旦 MySQL 的 bind-address 设为 127.0.0.1 但禁用了 socket,用 localhost 就会报 Can't connect to local MySQL server through socket。
排查方法:登录 MySQL 执行 SELECT @@socket; 看 socket 路径是否存在;再查 SELECT @@bind_address; 确认监听范围。
- 开发环境建议统一用
127.0.0.1,避免 socket 路径不一致引发的隐性问题 - Docker 场景下,
host必须填容器服务名(如mysql-db),不能写localhost—— 那是指 PHP 容器自身,不是数据库容器 - 若 MySQL 开启了
skip-networking,则只能用 socket 连,此时host必须为localhost,且需确认mysqli.default_socket在 php.ini 中指向正确的 socket 文件路径
密码为空时不要传 null 或空数组
PHP7.3 对空密码容忍度低。传 null、""(空字符串)或遗漏参数都会触发不同错误:mysqli_connect(): (HY000/1045): Access denied 或直接 PHP Warning。MySQL 允许空密码登录,但 PHP 层要求显式传空字符串 ""。
容易踩的坑:从配置文件读密码,若配置项被注释或未定义,$password 可能是 null 或 undefined,而非空字符串。
- 安全做法:初始化时兜底赋值:
$password = $password ?? ""; - 检查逻辑别写成
if (!$password) { $password = ""; }—— 因为0、false也会被转空串,误伤合法密码 - 生产环境严禁空密码;本地开发若真要用,确保 MySQL 用户授权语句中明确写了
IDENTIFIED BY ''
@'%' 和 @'localhost' 是两个独立账号,root@localhost 有权限不代表 root@127.0.0.1 也有;Docker 网络模式为 bridge 时,PHP 容器访问宿主机 MySQL 要用 host.docker.internal(Mac/Win)或宿主机真实 IP(Linux),而不是 127.0.0.1。php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











