我们使用Doctrine,一个PHP ORM。我创建了一个这样的查询:

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

然后在函数中,我添加了各种where子句和适当的东西,像这样

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

稍后,在execute()-ing该查询对象之前,我想打印出原始SQL以检查它,并这样做:

$q->getSQLQuery();

但是,这只打印准备好的语句,而不是完整的查询。我想看看它正在发送什么到MySQL,但相反,它正在打印一个准备好的语句,包括?是否有一些方法可以看到'full'查询?


当前回答

要打印出Doctrine中的SQL查询,请使用:

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

其他回答

你可以检查你的应用执行的查询,如果你把所有的查询都记录在mysql中:

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

会有更多的查询,不仅是一个你正在寻找,但你可以grep它。

->getSql();作品

编辑:

查看我使用的所有mysql查询

sudo vim /etc/mysql/my.cnf 

加上这两行:

general_log = on
general_log_file = /tmp/mysql.log

重新启动mysql

编辑2 如果你没有找到mysql的配置(它可以在很多地方),只需从mysql命令行设置这些变量。

mysql -u root -p 

SHOW VARIABLES LIKE 'general_log_file';
SHOW VARIABLES LIKE 'general_log';

SET GLOBAL general_log = 'on';
SET GLOBAL general_log_file = '/tmp/mysql.log';

//view the queries
sudo tail -f /tmp/mysql.log

这些设置的生命周期直到MySQL重新启动。或者是笔记本电脑。所以他们不是永久的-这在我看来是伟大的-我只需要他们当我调试时,我不需要担心编辑配置然后删除他们。如果您不删除日志记录,如果您忘记它,它可能会增长太多。

我为这个主题做了一些研究,因为我想调试生成的SQL查询并在SQL编辑器中执行它。从所有的答案中可以看出,这是一个技术性很强的话题。

当我假设最初的问题是基于dev-env时,目前缺少一个非常简单的答案。您可以只使用Symfony profiler中的构建。只需点击Doctrine标签,滚动到你想检查的查询。然后点击“查看可运行查询”,你可以直接在SQL编辑器中粘贴你的查询

更多的UI基础方法,但非常快,没有调试代码开销。

我的解决方案:

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

也许它对某些人有用:

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

修改了@dsamblas函数,当参数是日期字符串(如'2019-01-01')时工作,并且当有使用IN传递的数组时工作

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

. 所以做dsamblas写的所有事情,但是用这个替换startQuery,或者看看区别,然后添加我的代码。(以防他修改了他的功能,而我的版本没有修改)。

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

没有测试太多。