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