2009-06-07 20 views
40

Estoy jugando con MySQLi por el momento, tratando de descubrir cómo funciona todo. En mis proyectos actuales siempre me gusta hacer eco de una cadena de consulta durante la codificación, solo para asegurarme de que todo está correcto y para depurar mi código rápidamente. Pero ... ¿cómo puedo hacer esto con una declaración MySQLi preparada?Cómo hacer eco de una declaración preparada MySQLi?

Ejemplo:

$id = 1; 
$baz = 'something'; 

if ($stmt = $mysqli->prepare("SELECT foo FROM bar WHERE id=? AND baz=?")) { 
    $stmt->bind_param('is',$id,$baz); 
    // how to preview this prepared query before acutally executing it? 
    // $stmt->execute(); 
}

He estado yendo a través de esta lista (http://www.php.net/mysqli), pero sin ninguna suerte.


EDITAR

Bueno, si no es posible desde dentro MySQLi, tal vez me quedo con algo como esto:

function preparedQuery($sql,$params) { 
    for ($i=0; $i<count($params); $i++) { 
    $sql = preg_replace('/\?/',$params[$i],$sql,1); 
    } 
    return $sql; 
} 

$id = 1; 
$baz = 'something'; 

$sql = "SELECT foo FROM bar WHERE id=? AND baz=?"; 

echo preparedQuery($sql,array($id,$baz)); 

// outputs: SELECT foo FROM bar WHERE id=1 AND baz=something 

lejos de ser perfecto, obviamente, ya que sigue siendo bastante redundante — algo que quería evitar — y tampoco me da una idea de lo que se está haciendo con los datos de MySQLi. Pero supongo que de esta manera puedo ver rápidamente si todos los datos están presentes y en el lugar correcto, y me ahorrará un poco de tiempo en comparación con ajustar las variables manualmente en la consulta — que puede ser un problema con muchos vars. .

+3

Guau, no parece que haya una manera. Triste ... Esperaba poder cambiar a mysqli, pero necesito registrar todas las declaraciones SQL que se han ejecutado para un historial. –

+1

Probablemente pueda hacer que su servidor MySQL registre todas las consultas que reciba –

+0

Sí, eso es útil, pero no quiero registrar SELECTS y no ayuda mucho con la depuración ya que podría haber muchas consultas por segundo. –

Respuesta

9

No creo que puedas, al menos no de la manera que esperabas. Tendría que construir la cadena de consulta usted mismo y ejecutarla (es decir, sin utilizar una instrucción), o buscar o crear un contenedor que admita esa funcionalidad. El que yo uso es Zend_Db, y así es como lo haría:

$id = 5; 
$baz = 'shazam'; 
$select = $db->select()->from('bar','foo') 
         ->where('id = ?', $id) 
         ->where('baz = ?', $baz); // Zend_Db_Select will properly quote stuff for you 
print_r($select->__toString()); // prints SELECT `bar`.`foo` FROM `bar` WHERE (id = 5) AND (baz = 'shazam') 
+0

No funciona en mi caso. –

4

Sólo tienes que configurar a morir y la salida de la última consulta ejecutada. El manejo de errores debería brindarle información significativa que puede usar para corregir su consulta.

6

He tenido problemas con este en el pasado. Entonces, para evitarlo, escribí una pequeña función para construir el SQL para mí en base al SQL, los indicadores y las variables.

//////////// Test Data ////////////// 
$_GET['filmID'] = 232; 
$_GET['filmName'] = "Titanic"; 
$_GET['filmPrice'] = 10.99; 

//////////// Helper Function ////////////// 
function debug_bind_param(){ 
    $numargs = func_num_args(); 
    $numVars = $numargs - 2; 
    $arg2 = func_get_arg(1); 
    $flagsAr = str_split($arg2); 
    $showAr = array(); 
    for($i=0;$i<$numargs;$i++){ 
     switch($flagsAr[$i]){ 
     case 's' : $showAr[] = "'".func_get_arg($i+2)."'"; 
     break; 
     case 'i' : $showAr[] = func_get_arg($i+2); 
     break; 
     case 'd' : $showAr[] = func_get_arg($i+2); 
     break; 
     case 'b' : $showAr[] = "'".func_get_arg($i+2)."'"; 
     break; 
     } 
    } 
    $query = func_get_arg(0); 
    $querysAr = str_split($query); 
    $lengthQuery = count($querysAr); 
    $j = 0; 
    $display = ""; 
    for($i=0;$i<$lengthQuery;$i++){ 
     if($querysAr[$i] === '?'){ 
      $display .= $showAr[$j]; 
      $j++; 
     }else{ 
      $display .= $querysAr[$i]; 
     } 
    } 
    if($j != $numVars){ 
     $display = "Mismatch on Variables to Placeholders (?)"; 
    } 
    return $display; 
} 

//////////// Test and echo return ////////////// 

echo debug_bind_param("SELECT filmName FROM movies WHERE filmID = ? AND filmName = ? AND price = ?", "isd", $_GET['filmID'], $_GET['filmName'], $_GET['filmPrice']); 

También he construir una pequeña herramienta en línea para ayudar.

Mysqli Prepare Statement Checker

+0

Comprueba los $ i <$ numargs; debe ser $ i <$ numVars, numargs es la cuenta total de todos los argumentos de fc. Cámbielo y comenzará a trabajar. – Elensar

+0

¡Falta un control importante! Su herramienta y su función muestran un stmt de SQL correcto incluso si usa para reemplazar un qmark dentro de un nombre de columen. Un usuario debe saber que los parámetros no están permitidos en los nombres de las columnas, pero ese error es difícil de encontrar y esta función desafortunadamente no funciona aquí también. –

2

recientemente he actualizado este proyecto para incluir la integración compositor, pruebas unitarias y para manejar mejor los argumentos que aceptan por referencia (para ello es necesario actualizar a php 5.6).


En respuesta a una solicitud que he recibido en un proyecto que he creado para abordar este mismo problema usando PDO, he creado una extensión para mysqli en github que parece que aborda el problema:

https://github.com/noahheck/E_mysqli

Este es un conjunto de clases que extienden las clases nativas mysqli y mysqli_stmt para permitirle ver un ejemplo de la consulta que se ejecutará en el servidor db mediante la interpolación de los parámetros enlazados en la consulta preparada que le da acceso a cadena de consulta resultante como una nueva propiedad en el stmt objeto:

$mysqli = new E_mysqli($dbHost, $dbUser, $dbPass, $dbName); 

$query = "UPDATE registration SET name = ?, email = ? WHERE entryId = ?"; 

$stmt = $mysqli->prepare($query); 

$stmt->bindParam("ssi", $_POST['name'], $_POST['email'], $_POST['entryId']); 

$stmt->execute(); 

echo $stmt->fullQuery; 

resultará en:

UPDATE registration SET name = 'Sue O\'reilly', email = '[email protected]' WHERE entryId = 5569 

Tenga en cuenta que los valores de la fullQuery se escaparon apropiada teniendo en cuenta el conjunto de caracteres en el servidor db , lo que debería hacer que esta funcionalidad sea adecuada para, por ejemplo, archivos de registro, copias de seguridad, etc.

Hay algunas advertencias sobre el uso de esto, descrito en el archivo Léame en el proyecto github, pero, especialmente para el desarrollo, aprendizaje y prueba, esto debería proporcionar algunas funcionalidades útiles.

Como he descrito en el proyecto github, no tengo ninguna experiencia práctica con la extensión mysqli, y este proyecto se creó a petición de los usuarios de su proyecto hermano, por lo que cualquier comentario que pueda proporcionarse desde los desarrolladores que usen esto en la producción serán muy apreciados.

Descargo de responsabilidad - Como dije, hice esta extensión.

Cuestiones relacionadas