Ошибка привязки вложенного массива в подготовленный оператор mysql

Я избиваю голову над синтаксической ошибкой ниже. Я пытаюсь связать вмонтированный массив в подготовленный оператор, но я получаю следующую синтаксическую ошибку:

У вас есть ошибка в синтаксисе 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() . Вы думаете , что передаете список, разделенный запятыми, но на самом деле вы передаете только разделенную запятыми строку, которая рассматривается как одно значение . Это означает, что вы будете искать одну запись со значением «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 , которая имеет столько же символов, сколько количество элементов в массиве.

Затем вы связываете свои параметры с помощью 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() ожидая, что параметр два будет передан по ссылке:

Предупреждение: Параметр 2 для mysqli_stmt :: bind_param () должен быть ссылкой, значение указано

Это немного раздражает, но достаточно легко для работы. Чтобы обойти это, вы можете использовать следующую функцию:

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

Он просто создает массив значений, которые ссылаются на значения в $selected array. Этого достаточно, чтобы сделать 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)));