MySQLi动态创建的预处理语句失败:“没有为预准备语句中的参数提供数据”

时间:2015-07-22 11:26:27

标签: php mysqli 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查询在我使用查询时非常有效,但只是手动将?替换为过滤器,因此它似乎不是初始查询的问题,而是准备好的语句。非常感谢帮助。

注意:注释掉的echo用于调试目的,通常是禁用的,但是我已将它们留下来以显示我如何获得我当前拥有的信息。

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

2 个答案:

答案 0 :(得分:1)

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

答案 1 :(得分:0)

您似乎永远不会使用值$params$params2。你连接它们,但你的$stmt->bind_param()在哪里?它被评论了吗?

我也没有看到$conn->prepare("")。你省略了一些代码吗?

$conn被定义为mysqli对象,然后再次从未使用过。有些东西不在这里。

编辑:

尝试exec(&#34; \ $ stmt-&gt; bind_param(\ $ params \ $ params2);&#34;);我假设你以某种方式执行代码并转义变量 - 遵循这个逻辑你应该同时逃避params和params2吗?