Description du problème :
Nous savons tous que depuis PHP 5.1.0, PDO est une partie standard de PHP et fournit 3 classes PDO
, PDOStatement code> et.
PDOException
, PDOException
il va sans dire que la fonction et le positionnement sont très clairs d'après le nom.
Alors la question se pose : Pourquoi les deux classes PDO
et PDOStatement
existent-elles en même temps ?
Pourquoi y a-t-il de telles questions ? Regardez d'abord l'image ci-dessous (photo tirée du manuel du site officiel de @PHP) :
L'image montre les méthodes déclarées par les classes PDO
et PDOStatement
. On peut voir que bien que la plupart des méthodes fournies par ces deux classes soient différentes, le noyau. les méthodes sont évidemment Overlap ou Repeat, telles que :
PDO::query()
, PDO::exec()
exécutent tous deux une instruction SQL, mais les retours sont différents
PDOStatement::execute()
exécute également une instruction SQL, mais l'instruction a été prétraitée
PDOStatement::execute()
est correct, mais PDO::query()
et PDO::exec()
existent au niveau en même temps Quelle est la nécessité ? Cela entraînera également des difficultés d’utilisation et de compréhension.
Eh bien, même s'il y a une nécessité d'exister en même temps
alors il y a toujours un pointPourquoi ces deux classes existent-elles en même temps ? Au lieu d'une seule classe (s'il n'y a que la classe PDO
), que diriez-vous de faire ce que ces deux classes peuvent faire ensemble ?
Quelle est la relation entre la classe PDO
et la classe PDOStatement
?
Si la classe PDO
est utilisée pour exécuter SQL et gérer les connexions, et que la classe PDOStatement
est uniquement utilisée pour traiter les jeux de résultats, alors cela semble beaucoup plus confortable et fluide. .
J'espère que quelqu'un pourra expliquer les considérations de conception du PDO
de PHP
. Merci sincèrement~
Je crois comprendre que l'un est utilisé pour exécuter du SQL ordinaire et l'autre peut être utilisé pour la liaison de paramètres, etc....
Je vais vous dire ma compréhension personnelle. Veuillez me corriger s'il y a des erreurs.
Premier aperçu de la classe AOP
Vous pouvez voir que query() et prepare() renvoient un objet PDOStatement, ce qui signifie que PDOStatement peut exploiter l'ensemble de résultats.
En regardant à nouveau PDO::prepare, le manuel indique qu'il exécute une instruction préparée. En fait, il obtient une instruction préparée PDOStatement, puis exécute réellement SQL en appelant PDOStatement::execute().
Habituellement, certains de nos projets utilisent prepare pour exécuter des instructions SQL. Ceci est fait pour empêcher l'injection SQL et améliorer les performances des requêtes du même modèle SQL. Le contenu du manuel officiel est introduit :
La requête doit seulement être analysée (ou préparée). une fois, mais peut être exécuté plusieurs fois avec des paramètres identiques ou différents. Lorsque la requête est préparée, la base de données analysera, compilera et optimisera son plan d'exécution de la requête. Pour les requêtes complexes, ce processus peut prendre suffisamment de temps pour être visible. ralentir une application s'il est nécessaire de répéter la même requête plusieurs fois avec des paramètres différents. En utilisant une instruction préparée, l'application évite de répéter le cycle d'analyse/compilation/optimisation Cela signifie que les instructions préparées utilisent moins de ressources et s'exécutent donc plus rapidement. .
Les paramètres des instructions préparées n'ont pas besoin d'être cités ; le pilote gère automatiquement cela. Si une application utilise exclusivement des instructions préparées, le développeur peut être sûr qu'aucune injection SQL ne se produira (cependant, si d'autres parties du fichier sont utilisées). les requêtes sont en cours de construction avec des entrées sans échappement, l'injection SQL est toujours possible). exécute select, insert, update,deletePDO::query exécute une instruction SQL et, si elle est transmise, renvoie un objet PDOStatement
PDO::exec exécute une instruction SQL et renvoie le nombre de lignes affectées. Cette fonction ne renvoie pas de collection de résultats.
PDOStatement::execute a été introduit plus tôt. Il s'agit d'une sous-fonction sous PDOStatement. Une fonctionnalité est qu'elle prend en charge les paramètres de liaison sans prendre en compte les problèmes de sécurité de l'injection SQL. Une autre fonctionnalité est qu'elle prend en charge plusieurs exécutions, de la même manière que le modèle SQL. performance.
Si vous n'interrogez qu'une seule instruction, l'avantage d'utiliser la requête est que l'ensemble de résultats renvoyé par la requête peut être parcouru directement.
Si vous utilisez exec pour l'exécuter, il renverra uniquement le nombre de lignes affectées, pas le jeu de résultats PDOStatement. Vous ne pouvez pas le parcourir directement. Suivez les recommandations officielles pour utiliser la requête ou l'exécuter.
C'est à peu près ce que je comprends.
Les trois méthodes ci-dessus peuvent toutes exécuter SQL. Si vous trouvez cela déroutant, vous ne pouvez utiliser que la troisième méthode.
Si vous exécutez SQL avec des paramètres d'entrée, afin d'empêcher l'injection SQL, vous devez utiliser prepare:🎜Parce que tant que exec et query peuvent y parvenir, préparer+exécuter peut également y parvenir.
Et préparer+exécuter peut le faire. pour y parvenir, comme le prétraitement des requêtes paramétrées, exec et query ne peuvent pas être implémentés.
Exec et query apparaissent davantage pour plus de commodité. Par exemple, parfois les instructions SQL que nous exécutons n'ont pas de paramètres externes, alors l'utilisation de exec et query sera plus. concis, évidemment, exec est plus approprié pour exécuter une seule instruction d'opération d'écriture (INSERT/UPDATE/DELETE), car exec peut renvoyer directement les lignes affectées. Si vous utilisez une requête, vous devez appeler rowCount() pour obtenir les lignes affectées, telles que. as :
$db->query($sql)->rowCount();
$db->query($sql)->rowCount();
当如果你执行没有外来参数的SQL获取SELECT结果,这时则应该用query而不是exec:
$db->query($sql)->fetchAll();
Lorsque vous exécutez SQL sans paramètres externes pour obtenir le résultat SELECT, vous devez utiliser query au lieu d'exec :$db->query($sql)->fetchAll();