web-dev-qa-db-fra.com

Dans PHP avec PDO, comment vérifier la requête paramétrée SQL finale?

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 jetons)?

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

135
JB Hurteaux

Je pense donc que je répondrai enfin à ma propre question afin d’avoir une solution complète pour le compte rendu. Mais je dois remercier Ben James et Kailash Badu qui ont fourni les indices pour cela.

Réponse courte
Comme mentionné par Ben James: NO .
La requête SQL complète n'existe pas du côté PHP, car la requête avec les jetons et les paramètres sont envoyés séparément à la base de données. Ce n'est que du côté de la base de données requête existe.

Même essayer de créer une fonction pour remplacer les jetons du côté PHP ne garantirait pas que le processus de remplacement est identique à celui de SQL (des choses délicates comme le type de jeton, bindValue vs bindParam, ... )

Solution de contournement
C'est là 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 my.cnf (ou my.ini dans mon cas avec le serveur Wamp) et en ajoutant une ligne comme celle-ci:

log=[REPLACE_BY_PATH]/[REPLACE_BY_FILE_NAME]

Il suffit de ne pas l'exécuter en production !!!

53
JB Hurteaux

L'utilisation d'instructions préparées avec des valeurs paramétrées n'est pas simplement un autre moyen de créer dynamiquement une chaîne de code SQL. Vous créez une instruction préparée dans la base de données, puis vous ne transmettez que les valeurs de paramètre.

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

Vous ne pourrez pas obtenir une chaîne SQL comme SELECT * FROM ..., même si cela produirait des résultats équivalents, car une telle requête n'a jamais été réellement envoyée à la base de données.

27
Ben James

Vous pourrez peut-être utiliser PDOStatement->debugDumpParams. Voir the PHP documentation .

26
Michael

Je vérifie le journal des requêtes pour voir la requête exacte qui a été exécutée en tant qu'instruction préparée.

9
Kailash Badu

Au départ, j'ai évité d'activer la journalisation pour surveiller PDO, car 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écutez ce SQL dans phpMyAdmin ou dans tout autre environnement où vous pouvez avoir des privilèges élevés de base de données:

SET GLOBAL general_log = 'ON';

Dans un terminal, réduisez votre fichier journal. Le mien était là:

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

Vous pouvez rechercher vos fichiers mysql avec cette commande de terminal:

>ps auxww|grep [m]ysqld

J'ai trouvé que le PDO échappait à tout, vous ne pouvez donc 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 que cela crée:

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

Ce qui n'a pas créé d'erreur, mais un résultat vide. Au lieu de cela, j'avais besoin d'utiliser

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

obtenir

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

Lorsque vous avez terminé, exécutez:

SET GLOBAL general_log = 'OFF';

ou bien vos journaux deviendront énormes.

5
Chris Adams

Le moyen le plus simple consiste à lire le fichier journal d’exécution de mysql, ce que vous pouvez faire au moment de l’exécution.

Il y a une bonne explication ici:

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

1
Cristiano

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 instruction, j'ai une autre variable qui ressemble à ceci:

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

Où:
$column est mon gage
$param est la valeur réelle attribuée au jeton
$this->fullStmt est ma déclaration d'impression uniquement avec les jetons remplacés

Ce qu'il fait est simplement remplacer les jetons par des valeurs lorsque la véritable affectation d'un PDO se produit.

J'espère ne pas vous avoir confondu et au moins vous avoir dirigé dans la bonne direction.

1
6bytes

Je ne crois pas que vous puissiez le faire, bien que j'espère que quelqu'un me prouvera le contraire.

Je sais que vous pouvez imprimer la requête et que 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
Scott Saunders