【问题标题】:MySQLi dynamically created prepared statement fails: "No data supplied for parameters in prepared statement"MySQLi 动态创建的准备语句失败:“没有为准备语句中的参数提供数据”
【发布时间】:2015-07-22 11:26:27
【问题描述】:

我有一段代码从 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-&gt;bind_param($params, $_GET["filter_user_agent"]);

此外,当我使用查询但只是手动将?s 替换为过滤器时,SQL 查询可以完美运行,因此它似乎不是初始查询的问题,而是准备好的语句。非常感谢您的帮助。

注意:被注释掉的 echos 用于调试目的,通常被禁用,但我将它们留在其中以显示我如何获得我目前拥有的信息。

编辑:在下面回答了我自己的问题 - 错误是我使用 exec() - exec使用外部 shell 命令的函数,而我想要的是 eval()eval评估字符串输入并将其作为 PHP 脚本执行。

【问题讨论】:

  • 试试 exec("\$stmt->bind_param(\$params\$params2);");我假设您以某种方式执行代码并转义变量 - 按照该逻辑您应该同时转义 params 和 params2,也许?编辑:如果正确,我将其移至答案。

标签: php mysqli prepared-statement


【解决方案1】:

原来我只是误认为exec() 的功能。 (Python 太多了?)exec() 运行一个外部 shell 命令,而我正在寻找的是 eval(),它评估并运行作为 PHP 代码输入的任何字符串。

【讨论】:

    【解决方案2】:

    看起来您从未真正使用过值$params$params2。您将它们连接起来,但是您的$stmt-&gt;bind_param() 在哪里?被注释掉了?

    我也没有看到$conn-&gt;prepare("")。是不是省略了一些代码?

    $conn 被定义为 mysqli 对象,然后再一次从未使用过。有点不对劲。

    编辑:

    试试 exec("\$stmt->bind_param(\$params\$params2);");我假设您以某种方式执行代码并转义变量 - 按照该逻辑您应该转义 params 和 params2,也许?

    【讨论】:

    • 是的,我设法以某种方式省略了代码中最重要的部分。不过,我现在已经将其重新编辑了。旁注:作为评论可能会更好。
    • exec("\$stmt->bind_param(\$params$params2);");这是什么鬼?
    • 我把它作为一个答案,因为你的脚本不起作用的原因是缺少绑定方法和缺少 mysqli 对象的使用。那么很难给你一个更好的答案:)
    • 在双引号中,未转义的变量将从字符串内部计算。例如,$foo='bar'; echo "super $foo" 将返回“超级吧”。这不会发生在单引号中。这只是一种更紧凑的方式,而不是相当丑陋的"foo".$bar."baz"
    • 回复编辑:exec的原因是$params2是一个看起来像, $_GET["filter_phone"], $_GET["filter_appver"]的变量,并且在exec中没有转义,所以最终的代码去进入exec 看起来像这样:$stmt-&gt;bind_param($params, $_GET["filter_user_agent"]);exec 是向$stmt-&gt;bind_param() 添加额外参数所必需的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-16
    相关资源
    最近更新 更多