[Php] Doctrine - Как распечатать реальный sql, а не только подготовленное заявление?


Answers

Пример..

$qb = $this->createQueryBuilder('a');
$query=$qb->getQuery();

Показать SQL: $sql=$query->getSQL();

Показать параметры: $parameters=$query->getParameters();

Question

Мы используем Doctrine, PHP ORM. Я создаю такой запрос:

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

а затем в функции, которую я добавляю в различных местах, где это необходимо,

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

Позже, перед execute() этого объекта запроса, я хочу распечатать необработанный SQL, чтобы проверить его и сделать следующее:

$q->getSQLQuery();

Однако это выводит только подготовленный оператор, а не полный запрос. Я хочу посмотреть, что он отправляет в MySQL, но вместо этого распечатывает подготовленное заявление, в том числе ? «S. Есть ли способ увидеть «полный» запрос?




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



Я создал Doctrine2 Logger, который делает именно это. Он «гидратирует» параметризованный sql-запрос со значениями, используя собственные типы данных Doctrine 2.

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

Пример использования :; Следующий мир кода будет отражать на стандартном выходе любые предложения INSERT, UPDATE, DELETE SQL, сгенерированные с помощью $ em Entity Manager,

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



Чтобы распечатать SQL-запрос в Doctrine, используйте:

$query->getResult()->getSql();



Вы можете использовать :

$query->getSQL();

Если вы используете MySQL, вы можете использовать Workbench для просмотра запущенных операторов SQL. Вы также можете использовать просмотр текущего запроса из mysql, используя следующее:

 SHOW FULL PROCESSLIST \G



getSqlQuery() технически показывает всю команду SQL, но это намного более полезно, когда вы также можете увидеть параметры.

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

Чтобы сделать этот шаблон более многоразовым, есть хороший подход, описанный в comments в Raw SQL из Doctrine Query Object .




Вы можете легко получить доступ к параметрам SQL, используя следующий подход.

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

Поэтому, если вы напечатали $param_values и $col_names , вы можете получить значения параметров, проходящие через имена sql и соответствующих столбцов.

Примечание. Если $param возвращает массив, вам нужно повторить его, поскольку параметры внутри IN (:?) Обычно появляются как вложенный массив.

Если вы нашли другой подход, пожалуйста, будьте любезны поделиться с нами :)

Спасибо!