Pregunta

Estamos utilizando Doctrina, un ORM PHP. Estoy creando una consulta como la siguiente:

$q = Doctrine_Query::create()->select('id')->from('MyTable');

y luego en la función que estoy añadiendo en varias cláusulas where y cosas según el caso, como este

$q->where('normalisedname = ? OR name = ?', array($string, $originalString));

Más tarde, antes de que execute()-ción objeto de consulta, quiero imprimir el SQL en bruto con el fin de examinarlo, y hacer esto:

$q->getSQLQuery();

Sin embargo, eso sólo imprime la declaración preparada, no la consulta completa. Quiero ver lo que está enviando al MySQL, pero en su lugar se está imprimiendo una declaración preparada, incluyendo de ?. ¿Hay alguna manera de ver la consulta 'completa'?

¿Fue útil?

Solución

La doctrina no está enviando una "consulta SQL real" para el servidor de base de datos: que en realidad está utilizando comandos preparados, lo que significa:

  • El envío de la declaración, para que pueda ser preparado (esto es lo que se devuelve por $query->getSql())
  • Y, a continuación, el envío de los parámetros (devuelto por $query->getParameters())
  • y ejecución de las sentencias preparadas

Esto significa que no es un "verdadero" consulta SQL en el lado de PHP -. Embargo, la doctrina no puede mostrarla

Otros consejos

Un ejemplo de trabajo:

$qb = $this->createQueryBuilder('a');
$query=$qb->getQuery();
// SHOW SQL: 
echo $query->getSQL(); 
// Show Parameters: 
echo $query->getParameters();

Puede comprobar la consulta ejecutada por la aplicación si se registra todas las consultas en MySQL:

http://dev.mysql.com/doc/ RefMan / 5.1 / es / query-log.html

habrá más consultas no sólo el que usted está buscando, pero que puede grep para ello.

pero por lo general las obras ->getSql();

Editar:

para ver todas las consultas de MySQL que uso

sudo vim /etc/mysql/my.cnf 

y agregar esas 2 líneas:

general_log = on
general_log_file = /tmp/mysql.log

y reiniciar mysql

He creado un Registrador de Doctrine2 que hace exactamente esto. It "hidratos" la parametrizada de consultas SQL con los valores utilizando Doctrina 2 propios conversores de tipos de datos.

<?php


namespace Drsm\Doctrine\DBAL\Logging;
use Doctrine\DBAL\Logging\SQLLogger,
    Doctrine\DBAL\Types\Type,
    Doctrine\DBAL\Platforms\AbstractPlatform;
/**
 * A SQL logger that logs to the standard output and
 * subtitutes params to get a ready to execute SQL sentence

 * @author  dsamblas@gmail.com
 */
class EchoWriteSQLWithoutParamsLogger implements SQLLogger

{
    const QUERY_TYPE_SELECT="SELECT";
    const QUERY_TYPE_UPDATE="UPDATE";
    const QUERY_TYPE_INSERT="INSERT";
    const QUERY_TYPE_DELETE="DELETE";
    const QUERY_TYPE_CREATE="CREATE";
    const QUERY_TYPE_ALTER="ALTER";

    private $dbPlatform;
    private $loggedQueryTypes;
    public function __construct(AbstractPlatform $dbPlatform, array $loggedQueryTypes=array()){
        $this->dbPlatform=$dbPlatform;
        $this->loggedQueryTypes=$loggedQueryTypes;
    }
    /**
     * {@inheritdoc}
     */
    public function startQuery($sql, array $params = null, array $types = null)

    {
        if($this->isLoggable($sql)){
            if(!empty($params)){
                foreach ($params as $key=>$param) {
                    $type=Type::getType($types[$key]);
                    $value=$type->convertToDatabaseValue($param,$this->dbPlatform);
                    $sql = join(var_export($value, true), explode('?', $sql, 2));
                }

            }
            echo $sql . " ;".PHP_EOL;
        }
    }

    /**
     * {@inheritdoc}
     */
    public function stopQuery()
    {

    }
    private function isLoggable($sql){
        if (empty($this->loggedQueryTypes)) return true;
        foreach($this->loggedQueryTypes as $validType){
            if (strpos($sql, $validType) === 0) return true;
        }
        return false;
    }
}

Uso Ejemplo :; El siguiente código de la paz se hará eco en la salida estándar de cualquier INSERT, UPDATE, DELETE sentencias SQL generadas con $ em entidad gestora,

/**@var  \Doctrine\ORM\EntityManager $em */
$em->getConnection()
                ->getConfiguration()
                ->setSQLLogger(
                    new EchoWriteSQLWithoutParamsLogger(
                        $em->getConnection()->getDatabasePlatform(),
                        array(
                            EchoWriteSQLWithoutParamsLogger::QUERY_TYPE_UPDATE,
                            EchoWriteSQLWithoutParamsLogger::QUERY_TYPE_INSERT,
                            EchoWriteSQLWithoutParamsLogger::QUERY_TYPE_DELETE
                        )
                    )
                );

No hay otra consulta real, esto es el grado de preparación trabajan declaraciones. Los valores están obligados en el servidor de base de datos, no en la capa de aplicación.

Ver mi respuesta a esta pregunta: En PHP con PDO, ¿cómo comprobar el SQL última consulta parametrizada?

(repetido aquí por conveniencia:)

  

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

     

Entonces, ¿qué es, probablemente, enviado a la base de datos será un PREPARE ..., entonces SET ... y finalmente EXECUTE ....

     

Usted no será capaz de conseguir un poco de cadena SQL como SELECT * FROM ..., incluso si se produciría resultados equivalentes, porque hay tal consulta fue nunca llegó a enviar a la base de datos.

getSqlQuery() demuestran técnicamente todo el comando SQL, pero es mucho más útil cuando se puede ver los parámetros.

echo $q->getSqlQuery();
foreach ($q->getFlattenedParams() as $index => $param)
  echo "$index => $param";

Para hacer este patrón más reutilizables, hay un acercamiento agradable descrito en el comentarios en prima de SQL Query Objects Doctrina .

Mi solución:

 /**
 * Get SQL from query
 * 
 * @author Yosef Kaminskyi 
 * @param QueryBilderDql $query
 * @return int
 */
public function getFullSQL($query)
{
    $sql = $query->getSql();
    $paramsList = $this->getListParamsByDql($query->getDql());
    $paramsArr =$this->getParamsArray($query->getParameters());
    $fullSql='';
    for($i=0;$i<strlen($sql);$i++){
        if($sql[$i]=='?'){
            $nameParam=array_shift($paramsList);

            if(is_string ($paramsArr[$nameParam])){
                $fullSql.= '"'.addslashes($paramsArr[$nameParam]).'"';
             }
            elseif(is_array($paramsArr[$nameParam])){
                $sqlArr='';
                foreach ($paramsArr[$nameParam] as $var){
                    if(!empty($sqlArr))
                        $sqlArr.=',';

                    if(is_string($var)){
                        $sqlArr.='"'.addslashes($var).'"';
                    }else
                        $sqlArr.=$var;
                }
                $fullSql.=$sqlArr;
            }elseif(is_object($paramsArr[$nameParam])){
                switch(get_class($paramsArr[$nameParam])){
                    case 'DateTime':
                             $fullSql.= "'".$paramsArr[$nameParam]->format('Y-m-d H:i:s')."'";
                          break;
                    default:
                        $fullSql.= $paramsArr[$nameParam]->getId();
                }

            }
            else                     
                $fullSql.= $paramsArr[$nameParam];

        }  else {
            $fullSql.=$sql[$i];
        }
    }
    return $fullSql;
}

 /**
 * Get query params list
 * 
 * @author Yosef Kaminskyi <yosefk@spotoption.com>
 * @param  Doctrine\ORM\Query\Parameter $paramObj
 * @return int
 */
protected function getParamsArray($paramObj)
{
    $parameters=array();
    foreach ($paramObj as $val){
        /* @var $val Doctrine\ORM\Query\Parameter */
        $parameters[$val->getName()]=$val->getValue();
    }

    return $parameters;
}
 public function getListParamsByDql($dql)
{
    $parsedDql = preg_split("/:/", $dql);
    $length = count($parsedDql);
    $parmeters = array();
    for($i=1;$i<$length;$i++){
        if(ctype_alpha($parsedDql[$i][0])){
            $param = (preg_split("/[' ' )]/", $parsedDql[$i]));
            $parmeters[] = $param[0];
        }
    }

    return $parmeters;}

Ejemplo de uso:

$query = $this->_entityRepository->createQueryBuilder('item');
$query->leftJoin('item.receptionUser','users');
$query->where('item.customerid = :customer')->setParameter('customer',$customer)
->andWhere('item.paymentmethod = :paymethod')->setParameter('paymethod',"Bonus");
echo $this->getFullSQL($query->getQuery());

Se puede acceder fácilmente a los parámetros de SQL utilizando el siguiente enfoque.

   $result = $qb->getQuery()->getSQL();

   $param_values = '';  
   $col_names = '';   

   foreach ($result->getParameters() as $index => $param){              
            $param_values .= $param->getValue().',';
            $col_names .= $param->getName().',';
   } 

   //echo rtrim($param_values,',');
   //echo rtrim($col_names,',');    

Así que si usted imprimió el $param_values y $col_names, puede obtener los valores de los parámetros que pasan a través de los nombres de SQL y respectiva columna.

Nota:. Si $param devuelve una matriz, es necesario volver a iterar, como parámetros dentro IN (:?) por lo general viene es como una matriz anidada

Mientras tanto, si usted encuentra otro enfoque, por favor sea lo suficientemente amable para compartir con nosotros:)

Gracias!

La solución más clara:

 /**
 * Get string query 
 * 
 * @param Doctrine_Query $query
 * @return string
 */
public function getDqlWithParams(Doctrine_Query $query){
    $vals = $query->getFlattenedParams();
    $sql = $query->getDql();
    $sql = str_replace('?', '%s', $sql);
    return vsprintf($sql, $vals);
}

Puede utilizar:

$query->getSQL();

Si está utilizando MySQL Workbench puede utilizar para ver las sentencias SQL que se ejecutan. También puede utilizar la vista de la consulta que se ejecuta a partir de MySQL utilizando la siguiente:

 SHOW FULL PROCESSLIST \G

Tal vez puede ser útil para alguien:

// Printing the SQL with real values
$vals = $query->getFlattenedParams();
foreach(explode('?', $query->getSqlQuery()) as $i => $part) {
    $sql = (isset($sql) ? $sql : null) . $part;
    if (isset($vals[$i])) $sql .= $vals[$i];
}

echo $sql;
Solution:1
====================================================================================

function showQuery($query)
{
    return sprintf(str_replace('?', '%s', $query->getSql()), $query->getParams());
}

// call function  
echo showQuery($doctrineQuery);

Solution:2
====================================================================================

function showQuery($query)
{
    // define vars              
    $output    = NULL;
    $out_query = $query->getSql();
    $out_param = $query->getParams();

    // replace params
   for($i=0; $i<strlen($out_query); $i++) {
       $output .= ( strpos($out_query[$i], '?') !== FALSE ) ? "'" .str_replace('?', array_shift($out_param), $out_query[$i]). "'" : $out_query[$i];
   }

   // output
   return sprintf("%s", $output);
}

// call function  
echo showQuery($doctrineQueryObject);

Me escribió un registrador simple, que puede abrir una sesión de consulta con parámetros insertados. Instalación:

composer require cmyker/doctrine-sql-logger:dev-master

Uso:

$connection = $this->getEntityManager()->getConnection(); 
$logger = new \Cmyker\DoctrineSqlLogger\Logger($connection);
$connection->getConfiguration()->setSQLLogger($logger);
//some query here
echo $logger->lastQuery;
$sql = $query->getSQL();

$parameters = [];
    foreach ($query->getParameters() as $parameter) {
        $parameters[] = $parameter->getValue();
    }

$result = $connection->executeQuery($sql, $parameters)
        ->fetchAll();

@dsamblas modificados funcionan para el trabajo cuando los parámetros son cadenas de fecha como este '01/01/2019' y cuando hay matriz pasada usando IN como

$qb->expr()->in('ps.code', ':activeCodes'),

. Así que hacer todo lo que escribieron dsamblas, pero reemplace StartQuery con éste o ver las diferencias y añadir mi código. (En caso de que algo modificada en su función y mi versión no tiene modificaciones).

public function startQuery($sql, array $params = null, array $types = null)

{
    if($this->isLoggable($sql)){
        if(!empty($params)){
            foreach ($params as $key=>$param) {

                try {
                    $type=Type::getType($types[$key]);
                    $value=$type->convertToDatabaseValue($param,$this->dbPlatform);
                } catch (Exception $e) {
                    if (is_array($param)) {
                        // connect arrays like ("A", "R", "C") for SQL IN
                        $value = '"' . implode('","', $param) . '"';
                    } else {
                        $value = $param; // case when there are date strings
                    }
                }

                $sql = join(var_export($value, true), explode('?', $sql, 2));
            }

        }
        echo $sql . " ;".PHP_EOL;
    }
}

no prueba mucho.

Para imprimir una consulta SQL en Doctrina, utilice:

$query->getResult()->getSql();
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top