Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

Problema ao vincular um array implodido em uma instrução preparada pelo mysql


Deixe-me poupar alguns problemas e dizer que o que você está tentando fazer não funcionará de qualquer maneira. Você está vinculando apenas um parâmetro ao seu IN() chamada de função. Você pensa você está passando uma lista separada por vírgulas, mas na verdade você está apenas passando uma string separada por vírgulas que é tratada como um valor . Isso significa que você procurará um registro com um valor de "'[email protected] ', '[email protected] '" em vez de registros que correspondam a "[email protected] " ou "[email protected] ".

Para superar isso você precisa:
  1. Gere dinamicamente sua string de tipos
  2. Use call_user_func_array() para vincular seus parâmetros

Você pode gerar a string de tipos assim:
$types = str_repeat('s', count($selected));

Tudo isso cria uma string de s 's que são tantos caracteres quanto o número de elementos na matriz.

Você então vincularia seus parâmetros usando call_user_func_array() assim (observe que coloquei os parênteses de volta para o IN() função):
if ($stmt = $mysqli->prepare("DELETE FROM email_addresses WHERE email_addresses IN (?)")) {
    call_user_func_array(array($stmt, "bind_param"), array_merge($types, $selected));

Mas se você tentar isso, receberá um erro sobre mysqli_stmt::bind_param() esperando que o parâmetro dois seja passado por referência:

Isso é meio chato, mas fácil de contornar. Para contornar isso, você pode usar a seguinte função:
function refValues($arr){ 
    $refs = array(); 
    foreach($arr as $key => $value) 
        $refs[$key] = &$arr[$key]; 
    return $refs; 
} 

Ele apenas cria uma matriz de valores que são referências aos valores no $selected variedade. Isso é suficiente para fazer mysqli_stmt::bind_param() feliz:
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)));

Editar

A partir do PHP 5.6 agora você pode usar o ... operador para tornar isso ainda mais simples:
$stmt->bind_param($types, ...$selected);