Question

Nous utilisons Doctrine, un ORM PHP. Je crée une requête comme ceci:

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

puis dans la fonction que je ajoute dans diverses clauses et où les choses selon le cas, comme celui-ci

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

Plus tard, avant execute()-ment l'objet de la requête, je veux imprimer le SQL brut afin de l'examiner et faire ceci:

$q->getSQLQuery();

Cependant que seule imprime la déclaration préparée, pas la requête complète. Je veux voir ce qu'il envoie à MySQL, mais il est l'impression d'une déclaration préparée, y compris ceux des ?. Est-il possible de voir la requête « complet »?

Était-ce utile?

La solution

Doctrine n'envoie une « vraie requête SQL » au serveur de base de données: il utilise en fait des déclarations préparées, ce qui signifie:

  • Envoi de la déclaration, pour être préparé (ce qui est ce qui est renvoyé par $query->getSql())
  • Et puis, envoyer les paramètres (retourné par $query->getParameters())
  • et l'exécution des instructions préparées

Cela signifie qu'il n'y a jamais une « vraie » requête SQL sur le côté PHP -. Donc, la doctrine ne peut pas l'afficher

Autres conseils

Un exemple de travail:

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

Vous pouvez vérifier la requête exécutée par votre application si vous vous connectez toutes les requêtes dans une base MySQL:

http://dev.mysql.com/doc/ refman / 5.1 / fr / requête log.html

il y aura plus de requêtes non seulement celui que vous cherchez, mais vous pouvez grep pour elle.

mais généralement des œuvres ->getSql();

Edit:

pour afficher toutes les requêtes mysql que j'utilise

sudo vim /etc/mysql/my.cnf 

et ajouter ces 2 lignes:

general_log = on
general_log_file = /tmp/mysql.log

et redémarrez mysql

J'ai créé un enregistreur Doctrine2 qui fait exactement cela. Il « hydrate » la requête SQL avec les valeurs paramétrisé utilisant Doctrine 2 propres conversors de type de données.

<?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;
    }
}

Exemple d'utilisation :; La paix de code suivant l'écho sur la sortie standard tout INSERT, UPDATE, DELETE phrases SQL générées avec $ em entité gestionnaire,

/**@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
                        )
                    )
                );

Il n'y a pas d'autre requête réelle, voici comment fonctionnent les commandes préparées. Les valeurs sont liées dans le serveur de base de données, et non pas dans la couche d'application.

Voir ma réponse à cette question: en PHP avec PDO, comment vérifier la SQL finale de requête paramétrées?

(répété ici pour des raisons pratiques:)

  

Utilisation d'instructions préparées avec des valeurs paramétrées ne sont pas simplement une autre façon de créer dynamiquement une chaîne de SQL. Vous créez une déclaration préparée à la base de données, puis envoyer les valeurs des paramètres seul.

     

Alors, 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 elle produirait des résultats équivalents, parce qu'aucune requête n'a jamais été réellement envoyé à la base de données.

getSqlQuery() montre techniquement toute commande SQL, mais il est beaucoup plus utile lorsque vous pouvez voir les paramètres ainsi.

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

Pour rendre ce modèle plus réutilisable, il y a une approche bien décrite dans la section commentaires SQL brute de la doctrine de requête objet .

Ma solution:

 /**
 * 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;}

Exemple d'utilisation:

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

Vous pouvez facilement accéder aux paramètres SQL en utilisant l'approche suivante.

   $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,',');    

Donc, si vous avez imprimé le $param_values et $col_names, vous pouvez obtenir les valeurs des paramètres en passant par les noms de sql et de colonne respective.

Remarque:. Si $param retourne un tableau, vous devez re itérer, comme paramètres à l'intérieur IN (:?) vient habituellement est comme un tableau imbriqué

En attendant, si vous avez trouvé une autre approche, s'il vous plaît être assez aimable pour partager avec nous:)

Merci!

Solution plus claire:

 /**
 * 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);
}

Vous pouvez utiliser:

$query->getSQL();

Si vous utilisez MySQL, vous pouvez utiliser Workbench pour afficher en cours d'exécution des instructions SQL. Vous pouvez également utiliser afficher la requête en cours d'exécution de MySQL en utilisant les éléments suivants:

 SHOW FULL PROCESSLIST \G

Peut-être qu'il peut être utile pour quelqu'un:

// 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);

J'ai écrit un enregistreur simple, qui peut se connecter requête avec des paramètres insérés. Installation:

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

Utilisation:

$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 modifiés fonctionnent au travail lorsque les paramètres sont des chaînes de date comme celle-ci « 01/01/2019 » et quand il est passé en utilisant tableau IN comme

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

. Donc, tout ce qui écrit dsamblas, mais remplacer startQuery avec celui-ci ou voir les différences et ajouter mon code. (Dans le cas où il a modifié quelque chose dans sa fonction et ma version ne dispose pas de modifications).

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;
    }
}

n'a pas testé beaucoup.

Pour imprimer une requête SQL dans la doctrine, utilisez:

$query->getResult()->getSql();
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top