PDO支持命名参数和值绑定,MySQLi仅支持问号占位符及类型字符串绑定;PDO的bindValue()绑定值本身更安全常用,bindParam()绑定变量引用适合循环复用;MySQLi的bind_param()类型字符顺序必须严格匹配,错写不报错却易致异常。

PHP 中绑定参数不是靠某个叫 Bind 的函数,而是通过 PDO 或 MySQLi 的预处理语句(prepared statement)机制实现的;直接拼接 SQL 字符串再用 bind 一类词搜索,大概率踩进 SQL 注入或类型错配的坑。
PDO::prepare() + bindParam() /bindValue() 怎么选
PDO::prepare() 返回一个 PDOStatement 对象,后续才调用 bindParam() 或 bindValue()。两者关键区别在变量引用时机:
-
bindParam()绑定的是变量「引用」,执行execute()时才读取当前值 —— 适合循环中复用同一语句、每次改写变量内容 -
bindValue()绑定的是「值本身」,调用时立刻拷贝,后续变量变化不影响已绑定内容 —— 更安全、更常用,尤其参数来自函数返回值或字面量 - 如果绑定
NULL、布尔值或整数,bindValue()需显式传第 3 个参数指定类型(如PDO::PARAM_INT),否则可能被当字符串处理
示例:
$stmt = $pdo->prepare("SELECT * FROM users WHERE status = ? AND level > ?");
$stmt->bindValue(1, 'active', PDO::PARAM_STR);
$stmt->bindValue(2, 5, PDO::PARAM_INT);
$stmt->execute();
MySQLi 中 bind_param() 的类型字符串不能错
MySQLi::prepare() 后必须用 bind_param(),且第一个参数是类型字符串,每个字符对应一个占位符,顺序和数量必须严格一致:
-
i:整型(int) -
d:双精度浮点(double) -
s:字符串(string) -
b:BLOB(传资源或字符串,实际用得少) - 类型字符串长度 ≠ 参数个数 →
Warning: mysqli_stmt::bind_param(): Number of variables doesn't match number of parameters - 类型字符写错(比如该用
i写成s)→ 查询结果为空或类型转换异常,但不会报错,极难排查
正确写法:
$stmt = $mysqli->prepare("INSERT INTO logs (user_id, duration) VALUES (?, ?)");
$stmt->bind_param("id", $uid, $secs); // 注意:i 对应 $uid(int),d 对应 $secs(float/double)
$uid = 123;
$secs = 42.5;
$stmt->execute();
命名参数(:name)比问号 ? 更易维护,但有兼容陷阱
PDO 支持命名参数(如 :email),MySQLi **完全不支持**,硬写会静默失败或报错 SQLSTATE[HY093]。PDO 下命名参数的好处是顺序无关、可复用、可读性高:
- 同一个名字可在一条 SQL 中出现多次,
bindValue(':tag', $v)一次搞定全部 - 但注意:命名参数名不能是纯数字(如
:1),也不能含空格或特殊符号,下划线可以 - 某些旧版 PDO 驱动(如部分 Windows 上的 SQLite)对命名参数支持不完整,测试时务必覆盖目标环境
反例(看起来正常,实际不生效):
// ❌ MySQLi 不识别 :email,会当作普通字符串字面量
$mysqli->prepare("SELECT * FROM users WHERE email = ':email'");
<p>// ✅ PDO 正确用法
$stmt = $pdo->prepare("SELECT * FROM users WHERE email = :email AND role IN (:role1, :role2)");
$stmt->bindValue(':email', 'a@b.c');
$stmt->bindValue(':role1', 'admin');
$stmt->bindValue(':role2', 'editor');
</p>
真正容易被忽略的是:预处理语句的「绑定」只是数据通道,它不校验字段是否存在、不自动转义表名或列名、也不阻止你把 $_GET['order'] 直接拼进 SQL —— 动态字段名、表名、排序方向这类结构化内容,必须白名单过滤,不能靠绑定参数解决。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











