Lorsque vous utilisez l'extension MySQLI de PHP pour les opérations de base de données, nous utilisons souvent des instructions préparées pour améliorer la sécurité et les performances. Dans le même temps, les développeurs souhaitent souvent capturer avec précision les erreurs possibles telles que les erreurs de syntaxe SQL pendant l'exécution. Mais vous pouvez rencontrer un problème aussi déroutant:
Alors, que se passe-t-il? Cet article effectuera une analyse approfondie de ce problème et fournira des solutions pratiques.
Voir l'exemple de code suivant:
$mysqli = new mysqli("localhost", "user", "password", "testdb");
// Erreur de syntaxe:Un manquant FROM
$sql = "SELECT id name users WHERE id = ?";
$stmt = $mysqli->prepare($sql);
if (!$stmt) {
echo "Prepare failed: " . $mysqli->error; // La bonne façon de le faire
} else {
$stmt->bind_param("i", $id);
$id = 1;
$stmt->execute();
if ($stmt->error) {
echo "Execute error: " . $stmt->error; // 不会捕捉到Erreur de syntaxe
}
$stmt->close();
}
$mysqli->close();
Prepare failed: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version...
Comme vous pouvez le voir, les erreurs de syntaxe SQL ne saisissent pas du tout $ stmt-> , mais sont capturées par $ mysqli-> erreur dans l'étape Prepture () .
Nous devons comprendre la division du travail entre MySQLI et MySQLI_STMT en PHP:
MySQLI :: Préparez () est une méthode appelée par l'objet de connexion de la base de données. Si SQL a des erreurs de syntaxe, l'objet STMT ne sera pas du tout généré , donc $ stmt est faux .
MySQLI_STMT :: $ L'erreur n'a qu'une valeur après la préparation avec succès et une erreur d'exécution se produit (comme le type de variable de liaison ne correspond pas pendant l'exécution, les contraintes de clé étrangère échoue, etc.).
Ainsi, les erreurs de syntaxe SQL ne peuvent pas être prises avec $ STMT-> car elle ne créera même pas un objet STMT .
autrement dit:
Les erreurs de syntaxe SQL se produisent dans l'étape Préparer () et doivent être jugées par la valeur de retour de $ mysqli-> error ou mysqli :: prépare () , plutôt que d'attendre $ stmt-> execute () .
Réécrivez le code ci-dessus et adoptez la logique de gestion des erreurs plus sécurisée:
$mysqli = new mysqli("localhost", "user", "password", "testdb");
$sql = "SELECT id, name FROM users WHERE id = ?"; // Syntaxe correcte
$stmt = $mysqli->prepare($sql);
if (!$stmt) {
// 检查Erreur de syntaxe
die("SQL prepare failed: " . $mysqli->error);
}
$stmt->bind_param("i", $id);
$id = 1;
if (!$stmt->execute()) {
// Vérifiez les erreurs d'exécution
die("Execute failed: " . $stmt->error);
}
$result = $stmt->get_result();
$data = $result->fetch_assoc();
echo "User: " . $data['name'];
$stmt->close();
$mysqli->close();
Si vous utilisez l'interface AJAX pour soumettre des paramètres SQL, comme l'accès à une adresse comme celle-ci:
https://gitbox.net/api/get_user.php?id=1
Ensuite, vous épissez l'entrée de l'utilisateur dans SQL (dangereux!):
$id = $_GET['id'];
$sql = "SELECT * FROM users WHERE id = $id"; // Potentiel SQL Risque d'injection
Cette méthode d'écriture est facile à écrire SQL incorrectement lors de l'épissage, et Préparer () ne sera pas utilisée, et les erreurs sont plus difficiles à localiser. Par conséquent, la méthode d'écriture suivante est recommandée:
$sql = "SELECT * FROM users WHERE id = ?";
$stmt = $mysqli->prepare($sql);
$stmt->bind_param("i", $_GET['id']);
Cela évite non seulement l'injection SQL, mais rend également la vérification des erreurs claire et centralisée.
Les erreurs de syntaxe SQL ne peuvent être trouvées que dans l'étape de préparation () et ne peuvent pas être obtenues via $ stmt-> erreur .
Assurez-vous de vérifier la valeur de retour de PREEPL () et utilisez $ mysqli-> Erreur pour publier le message d'erreur.
Il est recommandé d'utiliser des déclarations de prétraitement pour empêcher l'injection, et il est plus facile de déboguer et d'attraper les erreurs.
Ce n'est qu'en comprenant la division des responsabilités entre MySQLI et MySQLI_STMT que nous pouvons écrire un code d'interaction de base de données plus robuste et sécurisé.