面向对象方式应使用 new mysqli() 实例化连接,而非 mysqli_connect();连接后立即调用 set_charset('utf8mb4');预处理需 prepare()+bind_param();事务需 begin_transaction()/commit();每次请求新建连接。

mysqli_connect() 不能直接用于面向对象方式
用 mysqli 做面向对象连接,不是调用函数 mysqli_connect(),而是实例化 mysqli 类。这个类构造函数本身就能完成连接,失败时抛出警告或返回 false(取决于是否开启异常模式)。
常见错误是混用过程式写法:mysqli_connect(...) 后又试图调用 $conn->query(...) —— 这会报 Fatal error: Call to a member function query() on boolean,因为 mysqli_connect() 返回的是资源或 false,不是对象。
- 正确做法:直接
$mysqli = new mysqli($host, $user, $pass, $db, $port, $socket) - 如果连接失败,
$mysqli->connect_error有具体错误信息,$mysqli->connect_errno是错误码 - 想让连接失败直接抛异常,可在 new 之前加
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT)
设置字符集必须在连接后立即执行
即使你在 new mysqli() 时传了 $charset 参数(第 6 个),它只影响客户端通知服务器“我打算用这个编码”,不保证连接层真正生效。MySQL 实际可能仍按服务端默认(如 latin1)解析请求,导致中文乱码或 Incorrect string value 错误。
- 安全做法:连接成功后立刻调用
$mysqli->set_charset('utf8mb4') - 别用
SET NAMES utf8mb4查询代替 —— 它不如set_charset()可靠,尤其在预处理语句场景下 -
utf8mb4是必须的,utf8在 MySQL 中只是utf8mb3的别名,不支持 emoji 和部分生僻汉字
预处理语句必须用 prepare() + bind_param() 配合
面向对象方式下,不能像过程式那样用 mysqli_prepare() 函数。所有操作都走对象方法链,且类型绑定不能省略。
立即学习“PHP免费学习笔记(深入)”;
典型错误是拼接变量进 SQL 字符串,或者忘记 bind_param() 就直接 execute(),结果查不到数据、插入空值,甚至触发 Number of variables doesn’t match number of parameters in prepared statement。
- 占位符统一用
?,不要用命名参数(MySQLi 不支持:name) -
bind_param()第一个参数是类型字符串:'s'(string)、'i'(int)、'd'(double)、'b'(blob);多个参数连写,如'si' - 变量必须传引用:用
bind_param('s', $name)而不是bind_param('s', $name)(PHP 7.4+ 允许值传递,但低版本仍需&$name)
事务控制要显式调用 begin_transaction() 和 commit()
MySQLi 面向对象不支持自动事务。即使你开了 AUTOCOMMIT=0,也得靠代码驱动。漏掉 commit() 或 rollback(),会导致连接关闭时自动回滚,你以为成功了,其实没持久化。
- 开始事务:用
$mysqli->begin_transaction()(PHP 5.5+),比$mysqli->query('START TRANSACTION')更清晰 - 提交:用
$mysqli->commit();失败时用$mysqli->rollback() - 注意:预处理语句在事务中正常工作,但
SELECT不会锁表,除非加FOR UPDATE或LOCK IN SHARE MODE
最容易被忽略的是连接复用和长连接管理:MySQLi 对象不是线程安全的,也不能跨请求复用;每次 HTTP 请求应新建对象,用完不需显式 close()(脚本结束自动释放),但高并发下建议主动 $mysqli->close() 避免连接数打满。











