189

PHP ORMであるDoctrineを使用しています。次のようなクエリを作成しています。

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

そして、このように、必要に応じてさまざまなwhere句やものを関数に追加しています

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

後で、execute()そのクエリ オブジェクトを -ing する前に、それを調べるために生の SQL を出力して、次のようにします。

$q->getSQLQuery();

ただし、完全なクエリではなく、準備されたステートメントのみを出力します。MySQL に何を送信しているのかを確認したいのですが、代わりに を含む準備済みステートメントを出力してい?ます。「完全な」クエリを表示する方法はありますか?

4

19 に答える 19

181

Doctrine は「実際の SQL クエリ」をデータベース サーバーに送信していません。実際には、準備されたステートメントを使用しています。つまり、次のことを意味します。

  • ステートメントを送信して準備します (これが によって返され$query->getSql()ます)
  • そして、パラメータを送信します( によって返されます$query->getParameters()
  • 準備されたステートメントの実行

これは、PHP 側に「実際の」SQL クエリが存在しないことを意味します — したがって、Doctrine はそれを表示できません。

于 2010-01-19T17:23:25.910 に答える
37

mysqlにすべてのクエリを記録すると、アプリによって実行されたクエリを確認できます。

http://dev.mysql.com/doc/refman/5.1/en/query-log.html

探しているクエリだけでなく、grepで検索できるクエリも増えます。

しかし、通常は->getSql();機能します

編集:

私が使用するすべてのmysqlクエリを表示するには

sudo vim /etc/mysql/my.cnf 

そしてそれらの2行を追加します:

general_log = on
general_log_file = /tmp/mysql.log

mysqlを再起動します

于 2011-10-27T11:39:13.277 に答える
18

まさにこれを行う Doctrine2 ロガーを作成しました。Doctrine 2独自のデータ型コンバーターを使用して、パラメーター化されたSQLクエリを値で「水和」します。

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

使用例:; 次の平和なコードは、$em Entity Manager で生成された INSERT、UPDATE、DELETE SQL 文を標準出力にエコーします。

/**@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
                        )
                    )
                );
于 2013-09-05T16:33:13.657 に答える
13

getSqlQuery()技術的には SQL コマンド全体を表示しますが、パラメーターも表示できるとさらに便利です。

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

このパターンをより再利用可能にするために、Doctrine Query Object からの Raw SQLのコメントで説明されている優れたアプローチがあります。

于 2012-05-14T04:59:16.567 に答える
13

他の実際のクエリはありません。これが、準備されたステートメントのしくみです。値は、アプリケーション層ではなく、データベース サーバーにバインドされます。

この質問に対する私の回答を参照してください: In PHP with PDO, how to check the final SQL parameterized query?

(便宜上、ここで繰り返します:)

パラメータ化された値を持つ準備済みステートメントを使用することは、SQL の文字列を動的に作成するための単なる別の方法ではありません。データベースで準備済みステートメントを作成し、パラメーター値のみを送信します。

したがって、おそらくデータベースに送信されるのはPREPARE ...、その後SET ...、最終的にEXECUTE ....

同等の結果が得られたとしても、のような SQL 文字列を取得することはできませんSELECT * FROM ...。これは、そのようなクエリが実際にデータベースに送信されたことがないためです。

于 2010-01-19T17:22:18.330 に答える
11

次の方法を使用して、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 (:?)は通常、ネストされた配列として渡されるためです。

それまでの間、別のアプローチを見つけた場合は、親切に私たちと共有してください:)

ありがとうございました!

于 2015-02-03T08:36:09.387 に答える
11

私の解決策:

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

使用例:

$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());
于 2014-12-23T14:03:00.657 に答える
5

使用できます:

$query->getSQL();

MySQL を使用している場合は、Workbench を使用して実行中の SQL ステートメントを表示できます。次を使用して、mysql から実行中のクエリを表示することもできます。

 SHOW FULL PROCESSLIST \G
于 2014-05-08T15:12:06.143 に答える
4

多分それは誰かに役立つかもしれません:

// 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;
于 2013-01-23T19:16:28.977 に答える
2

挿入されたパラメーターを使用してクエリをログに記録できる単純なロガーを作成しました。インストール:

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

使用法:

$connection = $this->getEntityManager()->getConnection(); 
$logger = new \Cmyker\DoctrineSqlLogger\Logger($connection);
$connection->getConfiguration()->setSQLLogger($logger);
//some query here
echo $logger->lastQuery;
于 2015-08-13T09:42:52.217 に答える
-3

Doctrine で SQL クエリを出力するには、以下を使用します。

$query->getResult()->getSql();
于 2015-01-27T20:33:58.243 に答える