MySQLi 动态创建的预处理语句失败:"No data supplied for parameters in prepared statement"
MySQLi dynamically created prepared statement fails: "No data supplied for parameters in prepared statement"
我有一段代码可以从 MySQL 数据库中读取崩溃日志和其他元数据,然后将其作为 JSON 发送回请求者(此代码由 AJAX 在另一页上运行)。可选地,可以使用 GET 指定过滤器,这会更改准备好的语句以仅过滤指定的结果 - 例如,仅显示来自一个应用程序版本的结果。这是有问题的代码:
$conn = new mysqli($sql_servername, $sql_username, $sql_password, "Crashes");
if ($conn->connect_error) {
//failed
die();
}
$sql="
SELECT ID,phone,appver,osver,user_agent,username,message,app_name,date_received FROM Crashes WHERE ";
$params="";
$params2="";
if (isset($_GET["filter_phone"])) {
$sql .= "phone = ? AND "; //i.e "WHERE phone = ? AND (...osver = ? AND appver = ? etc)"
$params.="s";
$params2.=', $_GET["filter_phone"]';
}
if (isset($_GET["filter_appver"])) {
$sql .= "appver = ? AND ";
$params.="s";
$params2.=', $_GET["filter_appver"]';
}
if (isset($_GET["filter_osver"])) {
$sql .= "osver = ? AND ";
$params.="s";
$params2.=', $_GET["filter_osver"]';
}
if (isset($_GET["filter_user_agent"])) {
$sql .= "user_agent = ? AND ";
$params.="s";
$params2.=', $_GET["filter_user_agent"]';
}
if (isset($_GET["filter_username"])) {
$sql .= "username = ? AND ";
$params.="s";
$params2.=', $_GET["filter_username"]';
}
if (isset($_GET["filter_message"])) {
$sql .= "message = ? AND ";
$params.="s";
$params2.=', $_GET["filter_message"]';
}
if (isset($_GET["filter_app_name"])) {
$sql .= "app_name = ? AND ";
$params.="s";
$params2.=', $_GET["filter_app_name"]';
}
$sql.="1";
//echo "$params: ".$params."<br>";
//echo "$params2: ".$params2."<br>";
//echo "<br>$stmt->bind_param($params$params2);<br>";
//echo var_dump($_GET);
$stmt = $conn->prepare($sql);
exec("$stmt->bind_param($params$params2);");
if ($stmt->execute()) {
//echo "<br>Success!";
} else {
//echo "<br>Failure: ".$stmt->error;
}
$result = $stmt->get_result();
$out = array();
while ($row = $result->fetch_assoc()) {
array_push($out, $row);
}
echo json_encode($out);
此代码在未指定过滤器时完美运行 - 但是,在指定任何过滤器时,语句将失败并显示错误 No data supplied for parameters in prepared statement
。我已经验证 exec()
中的代码应该 是(例如,如果设置了 user_agent 过滤器) $stmt->bind_param($params, $_GET["filter_user_agent"]);
此外,SQL 查询在我使用查询时工作得很好,但只是用过滤器手动替换 ?
s,所以它似乎不是初始查询的问题,而是准备好的陈述。将不胜感激。
注意:注释掉的 echo
s 用于调试目的,通常被禁用,但我将它们留在此处以显示我如何获得当前拥有的信息。
编辑:在下面回答了我自己的问题 - 错误是我正在使用 exec()
- executes 外部 shell 命令的函数,而我想要的是 eval()
,它 evaluates 字符串输入并将其作为 PHP 脚本执行。
看起来您从未真正使用值 $params
和 $params2
。你连接它们,但是你的 $stmt->bind_param()
在哪里?被注释掉了?
我也没有看到 $conn->prepare("")
。您是否遗漏了一些代码?
$conn
被定义为一个 mysqli 对象,然后再也没有使用过。这里有些地方不对。
编辑:
试试 exec("\$stmt->bind_param(\$params\$params2);");我假设您以某种方式执行代码并转义变量 - 按照该逻辑您应该同时转义 params 和 params2,也许?
原来我只是误会了 exec()
的功能。 (太多 Python?)exec()
运行一个 外部 shell 命令 ,而我正在寻找for was eval()
评估并运行作为 PHP 代码输入的任何字符串。
我有一段代码可以从 MySQL 数据库中读取崩溃日志和其他元数据,然后将其作为 JSON 发送回请求者(此代码由 AJAX 在另一页上运行)。可选地,可以使用 GET 指定过滤器,这会更改准备好的语句以仅过滤指定的结果 - 例如,仅显示来自一个应用程序版本的结果。这是有问题的代码:
$conn = new mysqli($sql_servername, $sql_username, $sql_password, "Crashes");
if ($conn->connect_error) {
//failed
die();
}
$sql="
SELECT ID,phone,appver,osver,user_agent,username,message,app_name,date_received FROM Crashes WHERE ";
$params="";
$params2="";
if (isset($_GET["filter_phone"])) {
$sql .= "phone = ? AND "; //i.e "WHERE phone = ? AND (...osver = ? AND appver = ? etc)"
$params.="s";
$params2.=', $_GET["filter_phone"]';
}
if (isset($_GET["filter_appver"])) {
$sql .= "appver = ? AND ";
$params.="s";
$params2.=', $_GET["filter_appver"]';
}
if (isset($_GET["filter_osver"])) {
$sql .= "osver = ? AND ";
$params.="s";
$params2.=', $_GET["filter_osver"]';
}
if (isset($_GET["filter_user_agent"])) {
$sql .= "user_agent = ? AND ";
$params.="s";
$params2.=', $_GET["filter_user_agent"]';
}
if (isset($_GET["filter_username"])) {
$sql .= "username = ? AND ";
$params.="s";
$params2.=', $_GET["filter_username"]';
}
if (isset($_GET["filter_message"])) {
$sql .= "message = ? AND ";
$params.="s";
$params2.=', $_GET["filter_message"]';
}
if (isset($_GET["filter_app_name"])) {
$sql .= "app_name = ? AND ";
$params.="s";
$params2.=', $_GET["filter_app_name"]';
}
$sql.="1";
//echo "$params: ".$params."<br>";
//echo "$params2: ".$params2."<br>";
//echo "<br>$stmt->bind_param($params$params2);<br>";
//echo var_dump($_GET);
$stmt = $conn->prepare($sql);
exec("$stmt->bind_param($params$params2);");
if ($stmt->execute()) {
//echo "<br>Success!";
} else {
//echo "<br>Failure: ".$stmt->error;
}
$result = $stmt->get_result();
$out = array();
while ($row = $result->fetch_assoc()) {
array_push($out, $row);
}
echo json_encode($out);
此代码在未指定过滤器时完美运行 - 但是,在指定任何过滤器时,语句将失败并显示错误 No data supplied for parameters in prepared statement
。我已经验证 exec()
中的代码应该 是(例如,如果设置了 user_agent 过滤器) $stmt->bind_param($params, $_GET["filter_user_agent"]);
此外,SQL 查询在我使用查询时工作得很好,但只是用过滤器手动替换 ?
s,所以它似乎不是初始查询的问题,而是准备好的陈述。将不胜感激。
注意:注释掉的 echo
s 用于调试目的,通常被禁用,但我将它们留在此处以显示我如何获得当前拥有的信息。
编辑:在下面回答了我自己的问题 - 错误是我正在使用 exec()
- executes 外部 shell 命令的函数,而我想要的是 eval()
,它 evaluates 字符串输入并将其作为 PHP 脚本执行。
看起来您从未真正使用值 $params
和 $params2
。你连接它们,但是你的 $stmt->bind_param()
在哪里?被注释掉了?
我也没有看到 $conn->prepare("")
。您是否遗漏了一些代码?
$conn
被定义为一个 mysqli 对象,然后再也没有使用过。这里有些地方不对。
编辑:
试试 exec("\$stmt->bind_param(\$params\$params2);");我假设您以某种方式执行代码并转义变量 - 按照该逻辑您应该同时转义 params 和 params2,也许?
原来我只是误会了 exec()
的功能。 (太多 Python?)exec()
运行一个 外部 shell 命令 ,而我正在寻找for was eval()
评估并运行作为 PHP 代码输入的任何字符串。