En PHP avec PDO, Comment vérifier la requête finale paramétrée par SQL? [dupliquer]

cette question a déjà une réponse ici:

en PHP, lorsque vous accédez à la base de données MySQL avec PDO avec une requête paramétrée, Comment Pouvez-vous vérifier la requête finale (après avoir remplacé tous les tokens)?

Est-il un moyen de vérifier ce qui est réellement exécuté par la base de données?

125
demandé sur JB Hurteaux 2009-11-24 00:56:09

9 réponses

Donc je pense que je vais enfin répondre à ma propre question afin d'avoir une solution complète pour l'enregistrement. Mais je dois remercier Ben James et Kailash Badu qui ont fourni les indices pour cela.

Réponse Courte

, Comme l'a mentionné Ben James: NON .

la requête SQL complète n'existe pas du côté de PHP, parce que la requête-avec-les jetons et les paramètres sont envoyés séparément au la base de données. Seulement du côté de la base de données la requête complète existe.

même en essayant de créer une fonction pour remplacer les tokens du côté de PHP ne garantirait pas que le processus de remplacement est le même que celui du SQL (des choses délicates comme le type de token, bindValue vs bindParam, ...)

contournement

c'est ici que je développe la réponse de Kailash Badu. En enregistrant toutes les requêtes SQL, nous pouvons voir ce qui est réellement exécuté sur le serveur. Avec mySQL, cela peut être fait en mettant à jour le my.cnf (ou mon.ini dans mon cas avec Wamp server), et l'ajout d'une ligne comme:

log=[REPLACE_BY_PATH]/[REPLACE_BY_FILE_NAME]

il suffit de ne pas exécuter cela dans la production!!!

51
répondu JB Hurteaux 2009-11-28 21:20:37

utiliser des instructions préparées avec des valeurs paramétrées n'est pas simplement une autre façon de créer dynamiquement une chaîne de caractères SQL. Vous créez une instruction préparée à la base de données, puis envoyez les valeurs des paramètres seulement.

donc ce qui est probablement envoyé à la base de données sera un PREPARE ... , puis SET ... et enfin EXECUTE ... .

vous ne serez pas en mesure d'obtenir une chaîne SQL comme SELECT * FROM ... , même si elle produirait des résultats équivalents, parce qu'une telle requête n'a jamais été envoyée à la base de données.

26
répondu Ben James 2009-11-23 22:17:33

vous pourriez utiliser PDOStatement->debugDumpParams . Voir la documentation PHP .

22
répondu Michael 2009-12-13 05:46:37

je vérifie le journal de requête pour voir la requête exacte qui a été exécutée comme déclaration préparée.

9
répondu Kailash Badu 2009-11-25 01:49:20

j'ai d'abord évité d'activer la journalisation pour surveiller AOP parce que je pensais que ce serait un problème, mais ce n'est pas difficile du tout. Vous n'avez pas besoin de redémarrer MySQL (après 5.1.9):

Exécuter ce SQL dans phpMyAdmin ou dans tout autre environnement où vous pouvez avoir élevé db privilèges:

SET GLOBAL general_log = 'ON';

dans un terminal, suivez votre fichier journal. Le mien était ici:

>sudo tail -f /usr/local/mysql/data/myMacComputerName.log

vous pouvez rechercher vos fichiers mysql avec ce terminal commande:

>ps auxww|grep [m]ysqld

j'ai trouvé que PDO échappe à tout, donc vous ne pouvez pas écrire

$dynamicField = 'userName';
$sql = "SELECT * FROM `example` WHERE `:field` = :value";
$this->statement = $this->db->prepare($sql);
$this->statement->bindValue(':field', $dynamicField);
$this->statement->bindValue(':value', 'mick');
$this->statement->execute();

parce qu'il crée:

SELECT * FROM `example` WHERE `'userName'` = 'mick' ;

qui n'a pas créé d'erreur, juste un résultat vide. Au lieu de cela, j'ai dû utiliser

$sql = "SELECT * FROM `example` WHERE `$dynamicField` = :value";

pour obtenir

SELECT * FROM `example` WHERE `userName` = 'mick' ;

quand vous avez terminé, exécutez:

SET GLOBAL general_log = 'OFF';

ou vos bûches seront énormes.

4
répondu Chris Adams 2013-04-12 06:46:28

Ce que j'ai fait pour imprimer cette requête est un peu compliqué mais ça marche :)

dans la méthode qui assigne des variables à mon énoncé j'ai une autre variable qui ressemble un peu à ceci:

$this->fullStmt = str_replace($column, '\'' . str_replace('\'', '\\'', $param) . '\'', $this->fullStmt);

où:

$column est-ce que mon jeton

$param est la valeur réelle attribuée au jeton

$this->fullStmt est ma déclaration d'impression seulement avec des jetons remplacés

ce qu'il fait est de simplement remplacer les tokens par des valeurs lorsque la véritable affectation AOP se produit.

j'espère que je ne t'ai pas embrouillé et au moins t'ai pointé dans la bonne direction.

1
répondu 6bytes 2009-11-23 22:38:11

la façon la plus facile de le faire est de lire le fichier journal d'exécution mysql et vous pouvez le faire à l'exécution.

il y a une belle explication ici:

Comment afficher les dernières requêtes exécutées sur MySQL?

1
répondu Cristiano 2017-05-23 12:02:23

Je ne crois pas que vous puissiez, même si j'espère que quelqu'un me prouvera que j'ai tort.

je sais que vous pouvez imprimer la requête et sa méthode toString vous montrera le sql sans les remplacements. Cela peut être pratique si vous construisez des chaînes de requête complexes, mais cela ne vous donne pas la requête complète avec des valeurs.

0
répondu Scott Saunders 2009-11-23 22:03:21

je pense que la façon la plus facile de voir le texte final de requête quand vous utilisez pdo est de faire l'erreur spéciale et regarder le message d'erreur. Je ne sais pas comment faire cela, mais quand je fais une erreur sql dans le cadre de Yii qui utilise pdo, je peux voir le texte de requête

-1
répondu shplintas 2013-06-04 11:39:02