繁体   English   中英

无法将内爆数组绑定到 mysql 准备好的语句中

[英]Trouble binding an imploded array into a mysql prepared statement

我对以下语法错误感到头疼。 我试图将内爆数组绑定到准备好的语句中,但出现以下语法错误:

您的 SQL 语法有错误; 检查与您的 MySQL 服务器版本相对应的手册,了解在“?”附近使用的正确语法。 在第 1 行

这是我的代码。 谁能看到我哪里出错了?

<?php 
include('config.php');

$selected = $_POST['selected'];

if ($stmt = $mysqli->prepare("DELETE FROM email_addresses WHERE email_addresses IN ?")) {

    $stmt->bind_param("s", "('" . implode("', '", $selected) . "')" );

    $stmt->execute();

    $stmt->close();

    print "ok";

} else {
    print $mysqli->error;
}

$mysqli->close();

?>

作为测试,我尝试了:

print "('" . implode("', '", $selected) . "')";

哪个正确地给了我

('me@me.com', 'you@you.com')

让我为您省去一些麻烦,并告诉您您尝试做的事情无论如何都行不通。 您只将一个参数绑定到IN()函数调用。 认为您正在传递一个逗号分隔的列表,但实际上您只传递了一个逗号分隔的字符串,该字符串被视为一个 value 这意味着你将寻找一个记录,值为“‘me@me.com’,‘you@you.com’”,而不是记录那场比赛“me@me.com”或“you@you.com” .

要克服这个问题,您需要:

  1. 动态生成您的类型字符串
  2. 使用call_user_func_array()绑定参数

您可以像这样生成类型字符串:

$types = str_repeat('s', count($selected));

所有这些都是创建一个s的字符串,它s字符数与数组中的元素数一样多。

然后你可以像这样使用call_user_func_array()绑定你的参数(注意我把括号放回IN()函数):

if ($stmt = $mysqli->prepare("DELETE FROM email_addresses WHERE email_addresses IN (?)")) {
    call_user_func_array(array($stmt, "bind_param"), array_merge($types, $selected));

但是如果你尝试这个,你会得到一个关于mysqli_stmt::bind_param()的错误,期望通过引用传递参数二:

警告:mysqli_stmt::bind_param() 的参数 2 应为引用,已给定值

这有点烦人,但很容易解决。 要解决此问题,您可以使用以下函数:

function refValues($arr){ 
    $refs = array(); 
    foreach($arr as $key => $value) 
        $refs[$key] = &$arr[$key]; 
    return $refs; 
} 

它只是创建一个值数组,这些值是对$selected数组中值的引用。 这足以让mysqli_stmt::bind_param()开心:

if ($stmt = $mysqli->prepare("DELETE FROM email_addresses WHERE email_addresses IN (?)")) {
    call_user_func_array(array($stmt, "bind_param"), array_merge($types, refValues($selected)));

编辑

从 PHP 5.6 开始,您现在可以使用...运算符使这更简单:

$stmt->bind_param($types, ...$selected);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM