mysqli_prepare必须用预处理防止SQL注入,因拼接字符串会使恶意输入如example.net' OR '1'='1直接执行;bind_param类型需匹配:s字符串、i整数、d浮点、b二进制;fetch_assoc前须调用get_result或bind_result;prepare、execute、get_result三处均需错误处理。

mysqli_prepare 为什么必须用预处理而不是拼接字符串
直接把用户输入塞进 SELECT * FROM Account_info WHERE domain_name = '$domain' 这类语句里,等于给攻击者开了后门。哪怕只传一个域名,恶意输入 example.net' OR '1'='1 就能让整个表被拖走。MySQLi 的 prepare() 把 SQL 结构和数据彻底分开,数据库先编译模板,再安全填入值,根本不会执行额外逻辑。
bind_param 的类型字符不能错:s、i、d、b 怎么选
bind_param() 第一个参数是类型字符串,每个字符对应后续一个变量:
-
s:字符串(如$domain、$name) -
i:有符号整数(如$id、$status) -
d:双精度浮点(如$price) -
b:blob 数据(极少用)
常见错误是把数字当字符串传——比如用 's' 绑定 $id = 123,虽然可能“看起来”能跑通,但会触发隐式类型转换,某些 MySQL 版本下导致索引失效或查询变慢。
fetch_assoc() 前必须调用 get_result() 或 bind_result()
执行 execute() 后,结果集不会自动可用。漏掉这步会得到空数组或警告:
- 用
get_result()+fetch_assoc()更直观,适合返回多行或字段名不确定的场景 - 用
bind_result($key)+fetch()更省内存,适合只取单个字段且已知结构的情况
例如查单个 account_key,用 bind_result($key) 更轻量;但如果还要同时拿 account_name 和 id,fetch_assoc() 更省事。
错误处理不能只靠 if($stmt) —— 要检查 prepare、execute、get_result 三处
很多人只在 prepare() 后判断是否为 false,但 execute() 可能失败(如超时、锁表),get_result() 也可能返回 null(比如 INSERT/UPDATE 语句误用了它)。实际代码中这三处都该加判断:
if (!$stmt = $mysqli->prepare($sql)) die('prepare failed: ' . $mysqli->error);if (!$stmt->execute()) die('execute failed: ' . $stmt->error);if (!($result = $stmt->get_result())) die('get_result failed: ' . $stmt->error);
尤其注意 $stmt->error 和 $mysqli->error 是不同对象的属性,混用会拿不到真正出错的位置。


















