2009-11-23 15 views
113

En PHP, al acceder a la base de datos MySQL con PDO con consulta parametrizada, ¿cómo se puede verificar la consulta final (después de haber reemplazado todos los tokens)?En PHP con PDO, ¿cómo verificar la consulta final parametrizada de SQL?

¿Hay alguna manera de comprobar qué se ejecuta realmente en la base de datos?

+2

Me gustaría que hubiera una manera de hacerlo. Me ha estado molestando por un tiempo. –

+1

Para PHP> = 5.1, eche un vistazo a http://www.php.net/manual/en/pdostatement.debugdumpparams.php – Mawg

+1

Hay un error en 'debugDumpParams()' - no se incluyen valores en la salida.La única forma de (fácilmente) verificar las consultas ejecutadas por 'mysql' es habilitar temporalmente el registro en my.cnf (h/t to @JB Hurteaux) –

Respuesta

49

Así que creo que por fin voy a responder a mi propia pregunta con el fin de tener una solución completa para el registro. Pero tengo que agradecer a Ben James y Kailash Badu que proporcionaron las pistas para esto.

respuesta Corto
Como se ha mencionado por Ben James: NO.
La consulta SQL completa no existe en el lado de PHP, ya que las fichas de consulta con-y los parámetros se envían por separado a la base de datos. Solo en el lado de la base de datos existe la consulta completa.

Incluso intentar crear una función para reemplazar tokens en el lado PHP no garantizaría que el proceso de reemplazo sea el mismo que el SQL (cosas complicadas como token-type, bindValue vs bindParam, ...)

Solución
Aquí es donde elaboro sobre la respuesta de Kailash Badu. Al registrar todas las consultas SQL, podemos ver lo que realmente se ejecuta en el servidor. con MySQL, esto se puede hacer mediante la actualización del my.cnf (o my.ini en mi caso con el servidor Wamp), y añadiendo una línea como:

log=[REPLACE_BY_PATH]/[REPLACE_BY_FILE_NAME] 

Así que no ejecute esto en la producción !! !

+1

Asegúrese de reiniciar 'mysql' para ver los cambios en' my.cnf' para tomar efecto. Después de ejecutar su consulta, asegúrese de comentar la línea de registro y reiniciar 'mysql' nuevamente para detener el registro. –

0

No creo que puedas, aunque espero que alguien me demuestre que estoy equivocado.

Sé que puede imprimir la consulta y su método toString le mostrará el sql sin los reemplazos. Esto puede ser útil si está creando cadenas de consulta complejas, pero no le proporciona la consulta completa con valores.

26

El uso de declaraciones preparadas con valores parametrizados no es simplemente otra forma de crear dinámicamente una cadena de SQL. Crea una declaración preparada en la base de datos y luego envía los valores de los parámetros solo.

Lo que probablemente se envíe a la base de datos será un PREPARE ..., luego SET ... y finalmente EXECUTE ....

No podrá obtener alguna cadena de SQL como SELECT * FROM ..., incluso si produjera resultados equivalentes, porque dicha consulta nunca fue realmente enviada a la base de datos.

+1

Aceptando esto por ahora ya que tiene sentido. No es muy conveniente para la depuración, entonces ... –

+2

¿Hay alguna forma de que podamos ver la "secuencia" de sentencias SQL que realmente se ejecuta? Tal vez todavía puede ser de alguna ayuda, mejor que nada. –

+0

'$ stmt-> debugDumpParams();' deberían acercarse. –

1

Lo que hice para imprimir esa consulta real es un poco complicado pero funciona :)

En el método que asigna las variables a mi declaración Tengo otra variable que se ve un poco como esto:

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

Dónde:
$column es mi testigo
$param es el valor real de ser asignado Token
$this->fullStmt es mi impresión única declaración con fichas reemplazados

Lo que hace es simplemente reemplazar tokens con valores cuando ocurre la asignación real de PDO.

Espero no haberlo confundido y al menos le haya apuntado en la dirección correcta.

+0

Sí, gracias. También pensé en una función personalizada para hacer un reemplazo manual de tokens después de haber visto la respuesta de Ben James. No es muy conveniente cuando hay varios tokens, pero podría haber una forma de automatizar esto (si podemos acceder a todos los enlaces creados) y crear una función genérica. Por otro lado, lo que quiero es realmente la consulta generada antes de la ejecución. Crear una función mía para hacer eso no garantiza que obtendré el mismo resultado (por ejemplo, teniendo en cuenta las comillas insertadas alrededor de los parámetros de cadena ...) –

9

Reviso el Registro de consultas para ver la consulta exacta que se ejecutó como una declaración preparada.

17

Usted puede ser capaz de utilizar PDOStatement->debugDumpParams. Ver the PHP documentation.

+3

Buena respuesta, pero para mostrar los valores de param [es posible que necesite un parche] (http://stackoverflow.com/a/3656529/819417). –

+0

+1 Esto probablemente debería haber sido aceptado como la respuesta. Permite mezclar SQL con otros rastreos de depuración de PHP, en lugar de tener que buscar en varios lugares. – Mawg

4

Al principio evité encender el registro para monitorear PDO porque pensé que sería una molestia pero no es difícil en absoluto. No es necesario reiniciar MySQL (después 5.1.9):

lo ejecutaron en phpMyAdmin o cualquier otro entorno en el que pueda tener altos privilegios DB:

SET GLOBAL general_log = 'ON'; 

En un terminal, el registro de la cola archivo. El mío era aquí:

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

Puede buscar los archivos de MySQL con este comando en el terminal:

>ps auxww|grep [m]ysqld 

encontré que DOP escapa todo, así que no se puede escribir

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

Porque crea:

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

que no creó un error, solo un resultado vacío. En lugar necesitaba usar

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

para obtener

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

Cuando haya terminado de ejecutar:

SET GLOBAL general_log = 'OFF'; 

o bien sus registros obtendrán enormes.

+2

Por lo tanto, ha hecho su consulta abierta a inyección SQL, felicidades :) –

+4

En realidad, no, en primer lugar, pdo no tiene forma de establecer columnas dinámicas de esta manera. Esta es la mejor manera de hacerlo. En segundo lugar, la configuración dinámica de los campos de esta manera: 'dynamicField = 'userName'' no deja espacio para la inyección. Siempre que valides los nombres de tus columnas en una lista blanca, es imposible aplicar este método de construcción de sql. – Louis

-1

Creo que la manera más fácil de ver el texto final de la consulta cuando se usa pdo es hacer un error especial y buscar un mensaje de error. No sé cómo hacer eso, pero cuando hago un error sql en yii framework que usa pdo, puedo ver el texto de consulta

Cuestiones relacionadas