最近由于升级PHP版本导致wordpress的一个插件运行时报错,也没有其他插件可供替代。俗话说,自己动手,丰衣足食。于是我开始自己编写插件。插件需要用到数据库中的内容,于是我编写查询查询语句,使用了据说较为安全的mysqli::prepare方法。但是有一个报错困扰了我很久。
报错内容为“Fatal error: Uncaught Error: Call to a member function bind_param() on boolean in”,中文直译为“致命错误:未捕获错误:调用中布尔值上的成员函数bind_param()”,问题代码如下:
PHP
$conn = new mysqli("db_host", "db_user", "db_pw", "db_name");
$stmt1 = $conn->prepare("SELECT col FROM tablename1 WHERE id=?");
$stmt1->bind_param("i", 1);
$stmt1->execute();
$stmt1->bind_result($col1);
while($stmt1->fetch()){
$stmt2 = $conn->prepare("SELECT col FROM tablename2 WHERE id=?");
$stmt2->bind_param("i", $col1);
$stmt2->execute();
$stmt2->bind_result(col2);
......
}
$stmt2->close();
$stmt1->close();
$conn->close();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15$conn=newmysqli("db_host","db_user","db_pw","db_name");
$stmt1=$conn->prepare("SELECT col FROM tablename1 WHERE id=?");
$stmt1->bind_param("i",1);
$stmt1->execute();
$stmt1->bind_result($col1);
while($stmt1->fetch()){
$stmt2=$conn->prepare("SELECT col FROM tablename2 WHERE id=?");
$stmt2->bind_param("i",$col1);
$stmt2->execute();
$stmt2->bind_result(col2);
......
}
$stmt2->close();
$stmt1->close();
$conn->close();
问题发生在上述代码的8行,也就是bind_param语句。阅读报错得知,错误原因未捕获,也就是说,虽然程序在执行到第8行时发现了问题,但是问题不一定出在第8行。有可能是因为前边某些地方的参数有未被发现的错误,代码执行到第8行时才发现了错误,但是不知道错误究竟发生在哪里。而且,前边也有一个bind_param,并没有报错。
往前看,似乎没什么问题。猜测,一个PHP文件中只允许同时定义一个mysqli_stmt对象吗?于是我对代码进行了修改,关闭第一个mysqli_stmt对象后再开启第二个mysqli_stmt对象:
$conn = new mysqli("db_host", "db_user", "db_pw", "db_name");
$stmt1 = $conn->prepare("SELECT col FROM tablename1 WHERE id=?");
$stmt1->bind_param("i", 1);
$stmt1->execute();
$stmt1->bind_result($col1);
if($stmt1->fetch()){
$param = $col1;
}else{
$param = false;
}
$stmt1->close();
if($param !== false){
$stmt2 = $conn->prepare("SELECT col FROM tablename2 WHERE id=?");
$stmt2->bind_param("i", $param);
$stmt2->execute();
$stmt2->bind_result(col2);
......
$stmt2->close();
}
$conn->close();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20$conn=newmysqli("db_host","db_user","db_pw","db_name");
$stmt1=$conn->prepare("SELECT col FROM tablename1 WHERE id=?");
$stmt1->bind_param("i",1);
$stmt1->execute();
$stmt1->bind_result($col1);
if($stmt1->fetch()){
$param=$col1;
}else{
$param=false;
}
$stmt1->close();
if($param!==false){
$stmt2=$conn->prepare("SELECT col FROM tablename2 WHERE id=?");
$stmt2->bind_param("i",$param);
$stmt2->execute();
$stmt2->bind_result(col2);
......
$stmt2->close();
}
$conn->close();
以上改写将先前的同时存在的stmt1和stmt2改写为了先结束一个再运行一个。
运行测试,成功!