Maison  >  Questions et réponses  >  le corps du texte

php - PDO和PDOStatement为什么会同时存在?这样的设计是出于什么考虑呢?

问题描述:
都知道自PHP 5.1.0 起,PDO就算是PHP的标配的一部分了,PDO提供了3个类PDOPDOStatementPDOExceptionPDOException这个类就不用说了,功能和定位啥的看名字都很清楚。

那么问题来了:为什么会同时存在PDOPDOStatement这两个类?

为什么会有这样的疑问,先看下图(图片截取自@PHP官网手册):

图片是PDOPDOStatement类所声明的方法,可以看出,这两个类提供的方法虽然绝大部分不同,但是明显核心方法有重叠或重复,比如:

PDOStatement::execute()还好说,而PDO::query()PDO::exec() 同时存在的必要性又是什么呢?而且还会造成使用和理解上面的不畅。

好吧,就算有同时存在的必要性
那么还是有一点为什么要同时存在这两个类呢?而不是一个类(假如只有 PDO类)就将这两个类所能做的事情一起做了呢?
PDO 类和 PDOStatement 类之间是什么关系呢?

如果 PDO 类用来执行SQL和管理链接,而 PDOStatement 类只用来处理结果集,那么感觉就舒服顺畅多了。

希望有大牛能给予解释 PHPPDO 这么设计的考虑是什么,真诚感谢~

我想大声告诉你我想大声告诉你2712 Il y a quelques jours742

répondre à tous(3)je répondrai

  • 曾经蜡笔没有小新

    曾经蜡笔没有小新2017-05-16 13:13:25

    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....

    répondre
    0
  • 仅有的幸福

    仅有的幸福2017-05-16 13:13:25

    Je vais vous dire ma compréhension personnelle. Veuillez me corriger s'il y a des erreurs.
    Premier aperçu de la classe AOP

    PDO::prepare — Prepares a statement for execution and returns a statement object
    PDO::query — Executes an SQL statement, returning a result set as a PDOStatement object

    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.

    répondre
    0
  • PHP中文网

    PHP中文网2017-05-16 13:13:25

    1.exec
    2.query
    3.prepare+execute

    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.
    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();

    Si vous exécutez SQL avec des paramètres d'entrée, afin d'empêcher l'injection SQL, vous devez utiliser prepare:🎜
    $sql = "SELECT * FROM `io_post` WHERE `id` IN (?, ?, ?)";
    $params = array(1, 3, 5); //$params是一个参数数组,元素按顺序一一对应$sql中的问号?占位符
    $stmt = $db->prepare($sql);
    $stmt->execute($params); //execute会自动对参数数组的每个元素进行bindValue
    $stmt->fetchAll(); //如SELECT结果集
    $stmt->rowCount(); //如INSERT/UPDATE/DELETE受影响的行

    répondre
    0
  • Annulerrépondre