我们使用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->getSql()返回的内容) 然后,发送参数(由$query->getParameters()返回) 执行准备好的语句

这意味着PHP端从来没有一个“真正的”SQL查询——因此Doctrine无法显示它。

其他回答

我写了一个简单的日志记录器,它可以记录插入参数的查询。 安装:

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;

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

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

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

$sql = $query->getSQL();
$obj->mapDQLParametersNamesToSQL($query->getDQL(), $sql);
echo $sql;//to see parameters names in sql
$obj->mapDQLParametersValuesToSQL($query->getParameters(), $sql);
echo $sql;//to see parameters values in sql

public function mapDQLParametersNamesToSQL($dql, &$sql)
{
    $matches = [];
    $parameterNamePattern = '/:\w+/';
    /** Found parameter names in DQL */
    preg_match_all($parameterNamePattern, $dql, $matches);
    if (empty($matches[0])) {
        return;
    }
    $needle = '?';
    foreach ($matches[0] as $match) {
        $strPos = strpos($sql, $needle);
        if ($strPos !== false) {
            /** Paste parameter names in SQL */
            $sql = substr_replace($sql, $match, $strPos, strlen($needle));
        }
    }
}

public function mapDQLParametersValuesToSQL($parameters, &$sql)
{
    $matches = [];
    $parameterNamePattern = '/:\w+/';
    /** Found parameter names in SQL */
    preg_match_all($parameterNamePattern, $sql, $matches);
    if (empty($matches[0])) {
        return;
    }
    foreach ($matches[0] as $parameterName) {
        $strPos = strpos($sql, $parameterName);
        if ($strPos !== false) {
            foreach ($parameters as $parameter) {
                /** @var \Doctrine\ORM\Query\Parameter $parameter */
                if ($parameterName !== ':' . $parameter->getName()) {
                    continue;
                }
                $parameterValue = $parameter->getValue();
                if (is_string($parameterValue)) {
                    $parameterValue = "'$parameterValue'";
                }
                if (is_array($parameterValue)) {
                    foreach ($parameterValue as $key => $value) {
                        if (is_string($value)) {
                            $parameterValue[$key] = "'$value'";
                        }
                    }
                    $parameterValue = implode(', ', $parameterValue);
                }
                /** Paste parameter values in SQL */
                $sql = substr_replace($sql, $parameterValue, $strPos, strlen($parameterName));
            }
        }
    }
}

你可以通过将sql prepared语句与绑定结合来构建一个sql字符串,就像这样:

$sql = str_replace_array('?', $query->getBindings(), $query->toSql())
str_replace_array(string $search, array $replacement, string $subject): string

PHP的str_replace_array函数将$subject中的每个$search实例依次替换为$replacement数组中的值。

也许它对某些人有用:

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