Mysql
 sql >> Base de données >  >> RDS >> Mysql

Problème de liaison d'un tableau implosé dans une instruction préparée mysql

Permettez-moi de vous éviter des ennuis et de vous dire que ce que vous essayez de faire ne fonctionnera pas de toute façon. Vous ne liez qu'un seul paramètre à votre IN() appel de fonction. Vous pensez vous transmettez une liste séparée par des virgules mais vous ne transmettez en fait qu'une chaîne séparée par des virgules qui est traitée comme une seule valeur . Cela signifie que vous chercherez un enregistrement avec une valeur de "'[email protected] ', '[email protected] '" au lieu des enregistrements qui correspondent à "[email protected] " ou "[email protected] ".

Pour surmonter cela, vous devez :

  1. Générez dynamiquement votre chaîne de types
  2. Utilisez call_user_func_array() pour lier vos paramètres

Vous pouvez générer la chaîne types comme ceci :

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

Tout cela ne fait que créer une chaîne de s 's qui contient autant de caractères que le nombre d'éléments dans le tableau.

Vous lieriez alors vos paramètres en utilisant call_user_func_array() comme ceci (remarquez que j'ai remis la parenthèse pour le IN() fonction):

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

Mais si vous essayez ceci, vous obtiendrez une erreur à propos de mysqli_stmt::bind_param() s'attend à ce que le paramètre deux soit passé par référence :

C'est un peu ennuyeux mais assez facile à contourner. Pour contourner cela, vous pouvez utiliser la fonction suivante :

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

Il crée simplement un tableau de valeurs qui sont des références aux valeurs dans le $selected déployer. C'est suffisant pour faire mysqli_stmt::bind_param() heureux :

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)));

Modifier

Depuis PHP 5.6, vous pouvez désormais utiliser le ... opérateur pour rendre cela encore plus simple :

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