De nombreuses bases de données plus matures prennent en charge le concept d'instructions préparées.
Que sont les déclarations préparées ? Considérez-le comme un modèle compilé du SQL que vous souhaitez exécuter, qui peut être personnalisé à l'aide de paramètres variables. Les déclarations préparées peuvent apporter deux avantages majeurs :
Une requête ne doit être analysée (ou prétraitée) qu'une seule fois, mais peut être exécutée plusieurs fois avec des paramètres identiques ou différents. Lorsqu'une requête est prête, la base de données analyse, compile et optimise le plan d'exécution de la requête. Ce processus prend plus de temps pour les requêtes complexes et peut ralentir considérablement votre application si la même requête doit être répétée plusieurs fois avec des paramètres différents. En utilisant des instructions préparées, vous pouvez éviter les cycles répétés d’analyse/compilation/optimisation. En termes simples, les instructions préparées utilisent moins de ressources et s'exécutent donc plus rapidement.
Les paramètres fournis aux instructions préparées n'ont pas besoin d'être mis entre guillemets ; le pilote gère cela automatiquement. Si votre application utilise uniquement des instructions préparées, vous pouvez être sûr qu'aucune injection SQL ne se produira. (Cependant, si d'autres parties de la requête sont construites à partir d'entrées non échappées, il existe toujours un risque d'injection SQL).
Les instructions préparées sont si utiles que leur seule fonctionnalité est que PDO simule le traitement lorsque le pilote ne le prend pas en charge. Cela garantit que les applications peuvent utiliser le même modèle d'accès aux données, que la base de données dispose ou non de telles fonctionnalités.
L'exemple suivant exécute une requête d'insertion en remplaçant les espaces réservés nommés correspondants par le nom et la valeur.
<?php$stmt = $dbh->prepare("INSERT INTO REGISTRY (name, value) VALUES (:name, :value)");$stmt->bindParam(':name', $name);$stmt- >bindParam(':value', $value);//Insérer une ligne $name = 'one';$value = 1;$stmt->execute();// Insérez une autre ligne avec des valeurs différentes $name = 'two';$value = 2;$stmt->execute();?>
L'exemple suivant exécute une requête d'insertion en remplaçant l'espace réservé ? par le nom et la valeur.
<?php$stmt = $dbh->prepare("INSERT INTO REGISTRY (nom, valeur) VALUES (?, ?)");$stmt->bindParam(1, $name);$stmt->bindParam(2, $value);//Insérer une ligne $name = 'one';$value = 1;$stmt->execute();// Insérez une autre ligne avec des valeurs différentes $name = 'two';$value = 2;$stmt->execute();?>
L'exemple suivant obtient des données basées sur la valeur clé dans le formulaire fourni. Les entrées de l'utilisateur sont automatiquement citées, il n'y a donc aucun risque d'attaques par injection SQL.
<?php$stmt = $dbh->prepare("SELECT * FROM REGISTRYwhere name = ?");if ($stmt->execute(array($_GET['name']))) { while ($row = $stmt->fetch()) { print_r($row }}?>
Si le pilote de base de données le prend en charge, l'application peut également lier les paramètres de sortie et d'entrée. Les paramètres de sortie sont souvent utilisés pour obtenir des valeurs à partir de procédures stockées. Les paramètres de sortie sont légèrement plus compliqués à utiliser que les paramètres d'entrée car lors de la liaison d'un paramètre de sortie, vous devez connaître la longueur du paramètre donné. Si la valeur liée à un paramètre est supérieure à la longueur recommandée, une erreur est générée.
<?php$stmt = $dbh->prepare("CALL sp_returns_string(?)");$stmt->bindParam(1, $return_value, PDO::PARAM_STR, 4000); // Appel de la procédure stockée $stmt-> exécuter ();print "la procédure a renvoyé $return_valuen";?>
Vous pouvez également spécifier des paramètres comportant à la fois des valeurs d'entrée et de sortie, avec une syntaxe similaire aux paramètres de sortie. Dans l'exemple suivant, la chaîne « hello » est transmise à la procédure stockée et lorsque la procédure stockée est renvoyée, hello est remplacée par la valeur renvoyée par la procédure stockée.
<?php$stmt = $dbh->prepare("CALL sp_takes_string_returns_string(?)");$value = 'hello';$stmt->bindParam(1, $value, PDO::PARAM_STR|PDO::PARAM_INPUT_OUTPUT, 4000 ); // Appel de la procédure stockée $stmt->execute();print "procédure renvoyée $valeurn";?>
<?php$stmt = $dbh->prepare("SELECT * FROM REGISTRY où nom LIKE '%?%'");$stmt->execute(array($_GET['name']));// Symbole d'espace réservé doit être utilisé dans toute la valeur $stmt = $dbh->prepare("SELECT * FROM REGISTRY où nom LIKE ?");$stmt->execute(array("%$_GET[name]%"));?>