English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Tutoriel PHP de base

Tutoriel PHP avancé

PHP & MySQL

Manuel de référence PHP

Instructions préparées PHP MySQL

Dans ce tutoriel, vous apprendrez à utiliser les phrases préparées avec PHP dans MySQL.

Qu'est-ce qu'une phrase préparée

Une phrase préparée (également appelée phrase paramétrée) est une simple requête SQL contenant des placeholders au lieu de valeurs de paramètres réelles. Lors de l'exécution de la phrase, ces placeholders sont remplacés par des valeurs réelles.

MySQLi prend en charge l'utilisation des placeholders anonymes (?), comme suit :

INSERT INTO persons (first_name, last_name, email) VALUES (?, ?, ?);

PDO prend en charge les placeholders anonymes (?) et les placeholders nommés. Les placeholders nommés commencent par un deux-points (:), suivi d'un identificateur, comme suit :

INSERT INTO persons (first_name, last_name, email)
VALUES (:first_name, :last_name, :email);

L'exécution des phrases préparées comprend deux phases : la préparation et l'exécution.

  • Préparer - Au cours de la phase de préparation, une phrase modèle SQL est créée et envoyée au serveur de base de données. Le serveur analyse le modèle de phrase, effectue des vérifications de syntaxe et d'optimisation de requête, et le stocke pour utilisation future.

  • Exécuter - Pendant l'exécution, les valeurs des paramètres sont envoyées au serveur. Le serveur crée une phrase à partir du modèle de phrase et de ces valeurs pour l'exécuter.

Les phrases préparées sont très utiles, en particulier lorsque vous utilisez des valeurs différentes (par exemple, une série de phrases) pour exécuter une instruction INSERT spécifique plusieurs fois. La partie suivante décrit certains des principaux avantages de leur utilisation.

Avantages de l'utilisation des phrases préparées

Une phrase préparée peut être exécutée de manière efficace pour la même instruction, car elle n'est analysée qu'une seule fois et peut être exécutée plusieurs fois. En raison du fait que seules les valeurs des placeholders sont transmises au serveur de base de données à chaque exécution, au lieu de la requête SQL complète, cela peut réduire au maximum l'utilisation de la bande passante.

Les phrases préparées offrent également une protection puissante pour prévenirInjection SQLCela est dû au fait que les valeurs des paramètres ne sont pas directement intégrées dans la chaîne de requête SQL. En utilisant des protocoles différents, les valeurs des paramètres et les requêtes sont envoyées séparément au serveur de base de données, ce qui ne l'interfère pas avec elle. Après l'analyse du modèle de phrase, le serveur utilise directement ces valeurs lors de l'exécution. C'est pourquoi les phrases préparées sont moins sujettes à des erreurs et sont considérées comme l'un des éléments les plus critiques de la sécurité de la base de données.

L'exemple suivant vous montrera comment fonctionne réellement la phrase préparée :

Exemple : méthode procédurale

<?php
/* Tentez de vous connecter au serveur MySQL. \
Serveur avec paramètres par défaut (utilisateur sans mot de passe \ */
$link = mysqli_connect("localhost", "root", "", "demo");
 
//Vérification de la connexion
if($link === false){
    die("Erreur : Impossible de se connecter. ". mysqli_connect_error());
}
 
//Utilisez l'instruction préparée
$sql = "INSERT INTO persons (first_name, last_name, email) VALUES (?, ?, ?)";
 
if($stmt = mysqli_prepare($link, $sql)){
    //Lié les variables en tant que paramètres à la requête préparée
    mysqli_stmt_bind_param($stmt, "sss", $first_name, $last_name, $email);
    
    /* Définir les valeurs des paramètres et exécuter, cette phrase insère une autre ligne. */
    $first_name = "Hermione";
    $last_name = "Granger";
    $email = "[email protected]";
    mysqli_stmt_execute($stmt);
    
    /* Définir les valeurs des paramètres et exécuter la phrase d'insertion de ligne. */
    $first_name = "Ron";
    $last_name = "Weasley";
    $email = "[email protected]";
    mysqli_stmt_execute($stmt);
    
    echo \

    echo "Erreur : Impossible de préparer la requête : $sql. " . mysqli_error($link);
}
 
//Fermez l'instruction
mysqli_stmt_close($stmt);
 
//Fermez la connexion
mysqli_close($link);
?>

Exemple : méthode orientée objet

<?php
/* Tentez de vous connecter au serveur MySQL. \
Serveur avec paramètres par défaut (utilisateur sans mot de passe \ */
$mysqli = new mysqli("localhost", "root", "", "demo");
 
//Vérification de la connexion
if($mysqli === false){
    die("Erreur : Impossible de se connecter. ". $mysqli->connect_error);
}
 
// Utilisez l'instruction préparée
$sql = "INSERT INTO persons (first_name, last_name, email) VALUES (?, ?, ?)";
 
if($stmt = $mysqli->prepare($sql)){
    // Lié les variables en tant que paramètres à la requête préparée
    $stmt->bind_param("sss", $first_name, $last_name, $email);
    
    /* Définir les valeurs des paramètres et exécuter.
    Exécuter cette instruction à nouveau pour insérer une autre ligne */
    $first_name = "Hermione";
    $last_name = "Granger";
    $email = "[email protected]";
    $stmt->execute();
    
    /* Définir les valeurs des paramètres et exécuter
        Instruction pour insérer la ligne */
    $first_name = "Ron";
    $last_name = "Weasley";
    $email = "[email protected]";
    $stmt->execute();
    
    echo "Dépôt réussi des enregistrements.";

    echo "Erreur : impossible de préparer la requête : $sql. " . $mysqli->error;
}
 
//Fermez l'instruction
$stmt->close();
 
//Fermez la connexion
$mysqli->close();
?>

Exemple : méthode PDO

<?php
/* Tentez de vous connecter au serveur MySQL. \
Serveur avec paramètres par défaut (utilisateur sans mot de passe \ */
try{
    $pdo = new PDO("mysql:host=localhost;dbname=demo", \
    // Définissez le mode d'erreur PDO sur les exceptions
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch(PDOException $e){
    die("Erreur : Impossible de se connecter. ". $e->getMessage());
}
 
//Tentez d'exécuter la requête d'insertion
try{
    //Utilisez l'instruction préparée
    $sql = \
    $stmt = $pdo->prepare($sql);
    
    //Liez les paramètres à l'instruction
    $stmt-bindParam(':first_name', $first_name, PDO::PARAM_STR);
    $stmt-bindParam(':last_name', $last_name, PDO::PARAM_STR);
    $stmt-bindParam(':email', $email, PDO::PARAM_STR);
    
    /* Définir les valeurs des paramètres et exécuter ,
      Exécuter cette instruction à nouveau pour insérer une autre ligne */
    $first_name = "Hermione";
    $last_name = "Granger";
    $email = "[email protected]";
    $stmt->execute();
    
    /* Définir les valeurs des paramètres et exécuter
        Instruction pour insérer la ligne */
    $first_name = "Ron";
    $last_name = "Weasley";
    $email = "[email protected]";
    $stmt->execute();
    
    echo \
} catch(PDOException $e){
    die("Erreur : Impossible de préparer/Exécuter la requête: $sql. " . $e->getMessage());
}
 
// Fermez l'instruction
unset($stmt);
 
//Fermez la connexion
unset($pdo);
?>

Comme vous pouvez le voir dans l'exemple ci-dessus, nous avons préparé une seule instruction INSERT, mais avons exécuté cette instruction plusieurs fois en passant différents ensembles de paramètres.

Utilisation du code (style de programmation)

Dans l'instruction INSERT SQL de l'exemple ci-dessus, le point d'interrogation est utilisé commefirst_name,last_nameetemailLe placeholder pour la valeur du champ.

La fonction mysqli_stmt_bind_param() lie les variables aux placeholders (? dans le modèle de requête SQL. Les placeholders (?) seront remplacés par les valeurs réelles stockées dans les variables à l'exécution. La chaîne de type définie en tant que deuxième paramètre, c'est-à-dire 'sss' pour la chaîne, spécifie que chaque variable liée est de type string (chaîne).

La chaîne de type de définition spécifie le type de données de la variable liée correspondante, et les paramètres sont les quatre types suivants:

  • i - integer (entier)

  • d - double (flottant à double précision)

  • s - string (chaîne)

  • b - BLOB (binary large object : objet binaire large)

Le nombre de variables et le nombre de caractères définis dans la chaîne de type doivent correspondre au nombre de placeholders dans le modèle de requête SQL.

Utiliser les entrées reçues par le biais du formulaire Web

Si vous vous souvenez du chapitre précédent, nous avons créé un formulaire HTML pourInsérer des données dans la base de donnéesIci, nous allons étendre cet exemple en exécutant des instructions de prétraitement. Vous pouvez utiliser le même formulaire HTML pour tester les exemples d'insertion suivants, mais assurez-vous simplement que l'attribut action du formulaire utilise le bon nom de fichier.

Voici le code PHP mis à jour pour l'insertion de données. Si vous regardez attentivement l'exemple, vous constaterez que nous n'utilisons pas mysqli_real_escape_string() comme dans l'exemple de la chapitre précédent pour échapper les entrées utilisateur. En raison de l'utilisation des requêtes préparées, les entrées utilisateur ne sont jamais directement substituées dans la chaîne de requête, donc il n'est pas nécessaire de les échapper correctement.

Exemple : méthode procédurale

<?php
/* Tentez de vous connecter au serveur MySQL. \
Serveur avec paramètres par défaut (utilisateur sans mot de passe \ */
$link = mysqli_connect("localhost", "root", "", "demo");
 
//Vérification de la connexion
if($link === false){
    die("Erreur : Impossible de se connecter. ". mysqli_connect_error());
}
 
//Utilisez l'instruction préparée
$sql = "INSERT INTO persons (first_name, last_name, email) VALUES (?, ?, ?)";
 
if($stmt = mysqli_prepare($link, $sql)){
    //Lier les variables aux paramètres de la requête préparée
    mysqli_stmt_bind_param($stmt, "sss", $first_name, $last_name, $email);
    
    //Définir les paramètres
    $first_name = $_REQUEST['first_name'];
    $last_name = $_REQUEST['last_name'];
    $email = $_REQUEST['email'];
    
    //
    if(mysqli_stmt_execute($stmt)){
        echo \
    
        echo "Erreur : Impossible d'exécuter la requête : $sql ". mysqli_error($link);
    }

    echo "Erreur : Impossible d'exécuter la requête : $sql ". mysqli_error($link);
}
 
// Fermez l'instruction
mysqli_stmt_close($stmt);
 
//Fermez la connexion
mysqli_close($link);
?>

Exemple : méthode orientée objet

<?php
/* Tentez de vous connecter au serveur MySQL. \
Serveur avec paramètres par défaut (utilisateur sans mot de passe \ */
$mysqli = new mysqli("localhost", "root", "", "demo");
 
//Vérification de la connexion
if($mysqli === false){
    die("Erreur : Impossible de se connecter. ". $mysqli->connect_error);
}
 
//Utilisez l'instruction préparée
$sql = "INSERT INTO persons (first_name, last_name, email) VALUES (?, ?, ?)";
 
if($stmt = $mysqli->prepare($sql)){
    //Lié les variables en tant que paramètres à la requête préparée
    $stmt->bind_param("sss", $first_name, $last_name, $email);
    
    //Paramètres de configuration
    $first_name = $_REQUEST['first_name'];
    $last_name = $_REQUEST['last_name'];
    $email = $_REQUEST['email'];
    
    //
    -
        echo \
    
        echo \->error;
    }

    echo \->error;
}
 
//Fermez l'instruction
$stmt->close();
 
//Fermez la connexion
$mysqli->close();
?>

Exemple : méthode PDO

<?php
/* Tentez de vous connecter au serveur MySQL. \
Serveur avec paramètres par défaut (utilisateur sans mot de passe \ */
try{
    $pdo = new PDO("mysql:host=localhost;dbname=demo", \
    //Définissez le mode d'erreur PDO sur les exceptions
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch(PDOException $e){
    die("Erreur : Impossible de se connecter. ". $e->getMessage());
}
 
//Tentez d'exécuter la requête d'insertion
try{
    //Utilisez l'instruction préparée
    $sql = \
    $stmt = $pdo->prepare($sql);
    
    // Liez les paramètres à l'instruction
    $stmt->bindParam(':first_name', $_REQUEST['first_name'], PDO::PARAM_STR);
    $stmt->bindParam(':last_name', $_REQUEST['last_name'], PDO::PARAM_STR);
    $stmt->bindParam(':email', $_REQUEST['email'], PDO::PARAM_STR);
    
    // Exécutez l'instruction préparée
    $stmt->execute();
    echo \
} catch(PDOException $e){
    die("Erreur : Impossible de préparer/Exécutez la requête $sql. ". ". $e->getMessage());
}
 
//Fermez l'instruction
unset($stmt);
 
//Fermez la connexion
unset($pdo);
?>

Attention :Bien que l'entrée utilisateur ne nécessite pas d'échappement dans les instructions de prétraitement, vous devez toujours vérifier le type et la taille des données reçues à partir de sources externes, et mettre en œuvre des limitations appropriées pour éviter l'utilisation des ressources système.