Doctrine-Jak wydrukować prawdziwy SQL, a nie tylko przygotowane oświadczenie?
Używamy Doctrine, PHP ORM. Tworzę takie zapytanie:
$q = Doctrine_Query::create()->select('id')->from('MyTable');
A następnie w funkcji dodaję w różnych gdzie klauzule i rzeczy, jak to
$q->where('normalisedname = ? OR name = ?', array($string, $originalString));
Później, przed execute()
- w tym obiekcie zapytania, chcę wydrukować surowy SQL, aby go zbadać, i zrobić to:
$q->getSQLQuery();
Jednak, że wypisuje tylko przygotowane oświadczenie, a nie pełne zapytanie. Chcę zobaczyć co wysyła do MySQL, ale zamiast tego drukuje czy jest jakiś sposób, aby zobaczyć "pełne" zapytanie?
14 answers
Doctrine nie wysyła "prawdziwego zapytania SQL" do serwera bazy danych : w rzeczywistości używa gotowych instrukcji, co oznacza:
- wysyłanie instrukcji, aby była przygotowana (to jest to, co jest zwracane przez
$query->getSql()
) - i następnie wysyłanie parametrów (zwracanych przez
$query->getParameters()
) - i wykonanie przygotowanych oświadczeń
Oznacza to, że nigdy nie ma "prawdziwego" zapytania SQL po stronie PHP - więc Doctrine nie może go wyświetlić.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-01 00:30:36
Przykład..
$qb = $this->createQueryBuilder('a');
$query=$qb->getQuery();
Show SQL: $sql=$query->getSQL();
Pokaż Parametry: $parameters=$query->getParameters();
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-11-05 14:21:19
Możesz sprawdzić zapytanie wykonane przez Twoją aplikację, jeśli zarejestrujesz wszystkie zapytania w mysql:
Http://dev.mysql.com/doc/refman/5.1/en/query-log.html
Będzie więcej zapytań nie tylko tych, których szukasz, ale możesz je uzyskać.
Ale zazwyczaj ->getSql();
działa
Edit:
Aby wyświetlić wszystkie zapytania mysql używam
sudo vim /etc/mysql/my.cnf
I dodaj te 2 linijki:
general_log = on
general_log_file = /tmp/mysql.log
I restart mysql
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-09 08:36:58
Stworzyłem Logger Doctrine2, który robi dokładnie to. "Hydratuje" parametryzowane zapytanie sql z wartościami przy użyciu własnego typu danych conversors.
<?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 [email protected]
*/
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;
}
}
Przykład Użycia:; Następujący spokój kodu będzie odbijał się echem na standardowym wyjściu każdego wstawiania,aktualizowania, usuwania zdań SQL wygenerowanych za pomocą $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
)
)
);
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-09-05 16:33:13
Nie ma innego prawdziwego zapytania, tak działają przygotowane instrukcje. Wartości są powiązane w serwerze bazy danych, a nie w warstwie aplikacji.
Zobacz moją odpowiedź na to pytanie: w PHP z PDO, jak sprawdzić ostateczne parametryzowane zapytanie SQL?
(powtórzone tutaj dla wygody:)
Używanie gotowych instrukcji z parametryzowanymi wartościami nie jest po prostu innym sposobem dynamicznego tworzenia ciągu SQL. Tworzysz przygotowane oświadczenie w bazie danych, a następnie wyślij same wartości parametrów.
Więc to, co prawdopodobnie zostanie wysłane do bazy danych, będzie
PREPARE ...
, następnieSET ...
i wreszcieEXECUTE ....
Nie będziesz w stanie uzyskać jakiegoś ciągu SQL, takiego jak
SELECT * FROM ...
, nawet jeśli przyniosłoby to równoważne wyniki, ponieważ takie zapytanie nigdy nie zostało wysłane do bazy danych.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 10:31:26
getSqlQuery()
technicznie pokazuje całe polecenie SQL, ale jest o wiele bardziej przydatne, gdy można zobaczyć parametry, jak również.
echo $q->getSqlQuery();
foreach ($q->getFlattenedParams() as $index => $param)
echo "$index => $param";
Aby uczynić ten wzór bardziej wielokrotnym, istnieje ładne podejście opisane w comments atRaw SQL from Doctrine Query Object .
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-05-14 04:59:16
Bardziej przejrzyste rozwiązanie:
/**
* 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);
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-10-08 07:32:14
Moje rozwiązanie:
/**
* 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 <[email protected]>
* @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;}
Przykład użycia:
$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());
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-12-23 14:03:00
Możesz łatwo uzyskać dostęp do parametrów SQL za pomocą następującego podejścia.
$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,',');
Więc jeśli wydrukowałeś $param_values
i $col_names
, możesz uzyskać wartości parametrów przechodzące przez SQL i odpowiednie nazwy kolumn.
Notatka: Jeśli $param
zwróci tablicę, musisz ją ponownie powtórzyć, ponieważ parametry wewnątrz IN (:?)
zwykle są w postaci zagnieżdżonej tablicy.
W międzyczasie, jeśli znalazłeś inne podejście, bądź uprzejmy i podziel się z nami:)
Dziękuję!
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-02-03 17:26:02
Możesz użyć :
$query->getSQL();
Jeśli używasz MySQL możesz użyć Workbench do wyświetlania uruchomionych poleceń SQL. Możesz również użyć widoku uruchomionego zapytania z mysql, używając następującego polecenia:
SHOW FULL PROCESSLIST \G
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-05-08 15:12:06
Może się komuś przyda:
// 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;
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-01-23 19:16:28
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);
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-03-22 05:44:20
Napisałem prosty logger, który może rejestrować zapytania z wstawionymi parametrami. Instalacja:
composer require cmyker/doctrine-sql-logger:dev-master
Użycie:
$connection = $this->getEntityManager()->getConnection();
$logger = new \Cmyker\DoctrineSqlLogger\Logger($connection);
$connection->getConfiguration()->setSQLLogger($logger);
//some query here
echo $logger->lastQuery;
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-13 09:42:52
Aby wydrukować zapytanie SQL w Doctrine, użyj:
$query->getResult()->getSql();
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-01-27 22:58:21