Extbase - 从查询中获取创建的SQL

9
我想从我的Typo3扩展中获取一些数据库表格。该扩展基于Extbase。
查询总是返回空,但数据存在。
我已尝试过这个方法:
$query = $this->createQuery();
$query->statement('SELECT * FROM `my_table`
    WHERE field = ? ORDER BY date DESC LIMIT 1',
    array($condition));

$results = $query->execute();

这个:
$query = $this->createQuery();

$query->matching($query->equals('field', $condition));
$query->setOrderings(array('date' => Tx_Extbase_Persistence_QueryInterface::ORDER_DESCENDING));
$query->setLimit(1);

$results = $query->execute();

两者都返回null作为结果。

有可能获取该类创建的SQL以查找错误吗?

我已经查看了一些extbase持久类,但没有找到线索。

编辑: 对于那些感兴趣的人..我找到了一个“解决方案”。

如果您使用statement()方法创建查询,则可以使用此函数打印查询。

echo $query->getStatement()->getStatement();

它不会替换占位符。 但是您可以使用此方法获取变量。
var_dump($query->getStatement()->getBoundVariables());

这是我找到的最佳解决方案,而不需要编辑extbase扩展。

您也可以使用Zend Server,它的“Z-Ray”可以自动收集所有数据库查询。 - giraff
这个回答解决了你的问题吗?如何在Extbase中调试查询? - cweiske
8个回答

6
在TYPO3 6.2中,您可以使用Extbase DebuggerUtility来调试查询。在 $query->execute() 前添加以下代码:
$queryParser = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Extbase\\Persistence\\Generic\\Storage\\Typo3DbQueryParser');
\TYPO3\CMS\Extbase\Utility\DebuggerUtility::var_dump($queryParser->parseQuery($query));

对于TYPO3 8.7+版本,请使用以下代码:

$queryParser = \TYPO3\CMS\Core\Utility\GeneralUtilityGeneralUtility::makeInstance(\TYPO3\CMS\Extbase\Persistence\Generic\Storage\Typo3DbQueryParser::class);
$doctrineQueryBuilder = $queryParser->convertQueryToDoctrineQueryBuilder($query);
$doctrineQueryBuilderSQL = $doctrineQueryBuilder->getSQL();
$doctrineQueryBuilderParameters = $doctrineQueryBuilder->getParameters();

5
请查看这个代码片段,虽然使用起来不太方便,但它非常有帮助:
通常你需要在buildQuery(array $sql)方法的结尾处添加这段代码(*) - 就在return $statement;之前。
if (in_array("your_table_name", $sql['tables'])) {
    var_dump($statement);
    print_r($statement);
}

(*) 类文件:

  • TYPO3版本:4.x:typo3/sysext/extbase/Classes/Persistence/Storage/Typo3DbBackend.php
  • TYPO3版本:6.x:typo3/sysext/extbase/Classes/Persistence/Generic/Storage/Typo3DbBackend.php

在6.2.x中...

您可以尝试在\TYPO3\CMS\Core\Database\DatabaseConnection::exec_SELECTquery方法中,仅在获取到$query后添加条件,如(修剪很重要!):

public function exec_SELECTquery($select_fields, $from_table, $where_clause, $groupBy = '', $orderBy = '', $limit = '') {
    $query = $this->SELECTquery($select_fields, $from_table, $where_clause, $groupBy, $orderBy, $limit);

    if (trim($from_table) == 'fe_users') {
        DebuggerUtility::var_dump($query);
    }

// rest of method

这个问题没有简单的解决方案吗?例如 $query->getRawSql() 这样的东西。 - alphanyx
我不知道这样的东西...如果有的话,我会在第一时间进行描述。我正在使用所描述的方法,并没有找到更好的替代方案。 - biesior
@Mateng:相信我,这可以节省很多时间 :) 我使用它来验证像 findPrevious() 这样的东西... 方法 :) - biesior
5
在6.2中,我找不到buildQuery方法。 - Valentin Despa

3

一种不需要更改任何Typo3核心代码且目前还没有在任何论坛上提到的简单方法是使用php中的“serialize()”方法:

$result = $query->execute();
echo (serialize($result));

在结果对象中,您可以找到SQL查询语句("statement;" ...)


2

对 biesiors 的回答进行改进:

由于 Extbase 在调用 buildQuery() 后替换了一些占位符,因此您可能更喜欢将调试输出放在 getObjectDataByQuery() 中,在 $this->replacePlaceholders($sql, $parameters, $tableName); 之后。

if (strpos($sql, "your_table_name.")) {
    debug($sql, 'my debug output');
};

另外,最好使用debug()替代var_dump()。
[文件: typo3\sysext\extbase\Classes\Persistence\Generic\Storage\Typo3DbBackend.php。版本6.1中第339行]:


1
$query = $this->createQuery();
$query->getQuerySettings()->setReturnRawQueryResult(TRUE);
$getHotelInfo = 'SELECT * FROM `my_table` WHERE field = ? ORDER BY date DESC LIMIT 1';
return $query->statement($getHotelInfo)->execute();

要执行查询,您需要在存储库上编写“setReturnQueryResult”


0
在使用 TYPO3 6.1 时,更清晰的调试语句的方法是使用 Typo3DbBackendquery parser
$parser = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Extbase\\Persistence\\Generic\\Storage\\Typo3DbBackend');
$params = array();
$queryParts = $parser->parseQuery($query, $params);

\TYPO3\CMS\Core\Utility\GeneralUtility::devLog('query', 'my_extension', 1, array('query' => $queryParts, 'params' => $params));

解析器返回一个包含生成的SQL语句不同部分的数组。
在TYPO3 6.2中,parseQuery方法被移动到Typo3DbQueryParser,并且失去了它的第二个参数。

0
我刚刚扩展了上面的片段,并添加了一个 $_GET 条件。 为了调试,只需在您的地址后面添加“?dbg_table=tx_some_of_my_tables”,然后您就可以开始了;-)
if (in_array($_GET['dbg_table'], $sql['tables'])) {
        echo('<div style="background: #ebebeb; border: 1px solid #999; margin-bottom: 20px; padding: 10px;"><pre style="white-space: normal">'.$statement.'</pre></div>');
    }

0

我建议将此设置放置在 typo3conf/LocalConfiguration.php 文件的 'SYS' 数组下

'SYS' => array(
......
'displayErrors' => 1,
'sqlDebug' => 1
.......
)

然后故意在查询中写入错误的字段名称,然后执行代码。 这将显示最后一次执行带有错误的查询。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接