2011-05-20 4 views
12
$statement = $db->prepare('SELECT blah FROM blah_table WHERE blahID IN (:a, :b, :c)'); 

Que faire si le nombre de paramètres est inconnu jusqu'à l'exécution? La seule chose que je peux penser à faire est un type de construction hacky de la chaîne sql pour faire autant de paramètres que j'ai besoin.PDO lier un nombre inconnu de paramètres?

+0

Vraiment, en marquant cela comme une copie d'une question plus récente? – Kickstart

+0

@Kickstart Pourquoi pas - si l'autre question est bonne et fournir des réponses utiles. – Eiko

+0

@Eiko - pourquoi marquer comme doublon plusieurs années après que la même personne a répondu à la copie et a donné essentiellement la même réponse comme un existant ici? – Kickstart

Répondre

4

Vous pouvez construire "IN (...)" string dynamiquement:

$in_string = '('; 
foreach ($array_of_parameters as $parameter) { 
    $in_string .= ':' . chr($i + 97) . ','; // Get the ASCII character 
} 
$in_string = substr($in_string, 0, -1) . ')'; 

$statement = $db->prepare("SELECT blah FROM blah_table WHERE blahID IN ($in_string)"); 
+8

Pourquoi voudriez-vous prendre la peine d'utiliser des espaces réservés nommés? Utilisant un ? fonctionne aussi bien sans le travail supplémentaire? – Paystey

11

Pas vraiment hacky, les boucles font partie du langage pour boucler un nombre variable de fois. En boucle sur chaque valeur à lier, créez un tableau d'objets de liaison que vous bouclez après avoir ajouté le code SQL.

2

Juste une autre façon de le faire plus court.

$values = array(1, 2, 3, 4); 
$sql = "SELECT * 
      FROM table 
     WHERE column IN (" . join(',', array_map(function() { return '?'; }, $values)) . ")"; 
$db->prepare($sql); 
$db->execute($values); 
+0

Il sera vraiment apprécié si vous fournissez quelques explications à votre code. –

+0

@IllegalArgument quelle partie souhaitez-vous expliquer? [rejoindre] (http://php.net/manual/fr/function.join.php), [array_map] (http://php.net/manual/fr/function.array-map.php) –

+1

@IllegalArgument Il utilise le fait que array_map accepte une fonction de rappel qui sera effectuée sur chaque élément du tableau. C'est un peu exagéré =) Quelque chose comme "?" . str_repeat (',?', count ($ arr) - 1) 'ou' rtrim (str_repeat ('?,', count ($ arr)), ',') 'suffirait, car vous voulez juste une question marque pour chaque élément du tableau. – nimmneun

0

Une façon de le faire sans boucle explicite mais en donnant des marqueurs spécifiques plutôt que des points d'interrogation.

$values_array = array(1, 3, 5, 7, 11); 
$sql = "SELECT * 
      FROM table 
     WHERE column IN (" . implode(",", array_map(function($in){return ':a'.$in;}, range(1, count($values)))) . ")"; 
$prep = $db->prepare($sql); 
$i = 1; 
foreach($values_array as $key=>$value) 
{ 
    $prep->bindValue(':a'.$i++, $values_array[$key]); 
} 

Il utilise plage pour générer un tableau de nombres de 1 au nombre d'éléments dans le tableau, array_map puis changer ces chiffres pour les préfixer avec: et un caractère (dans ce cas seulement). Ceci est dû uniquement à la tentative de débogage de quelque chose qui utilisait des points d'interrogation et échouait. Problème avéré être ailleurs (dû à la boucle à travers le tableau pour lier les valeurs et avoir des problèmes avec bind en utilisant la référence à la variable, qui a été changée dans chaque itération du tableau - atterrissant ayant la même valeur dans chacun des lier les positions), mais pensé que cela pourrait être utile à quelqu'un.

+0

Espérons que cela n'aidera personne. Comme l'utilisation des espaces réservés nommés dans ce cas est juste un [...]. Alors que pour éviter une boucle explicite, il suffit de l'éviter, comme indiqué dans l'autre réponse. –

+0

Dans les cas noddy peut-être vrai, mais si vous avez (par exemple) une paire de requêtes unionnées ayant les mêmes paramètres étant passés, être capable de boucler les paramètres une fois pour les lier à des espaces spécifiques plutôt que juste dans l'ordre les points d'interrogation sont utiles. – Kickstart

Questions connexes