TYPO3 8.x 比较 CustomRepository 中的日期时间(查询、约束)

TYPO3 8.x Compare DateTime in CustomRepository (Query, Constraints)

我正在尝试使用 TYPO3 存储库中的比较字段来调整我的查询,但并没有真正弄明白。有人知道如何正确调试吗? 我正在使用 TYPO3 8.x CMS。 (准确地说是 8.4)

<?php 
public function findActiveProducts() {

    $query = $this->createQuery();
    $constraints = array();

    $date = new \DateTime(midnight);
    // $date = new \DateTime(); // i tried to use the precise time to compare
    $today = $date->format('Y-m-d H:i:s');
    // $today = $date->format('Y-m-d'); // 1st try (the field value in db)
    // $today = $date->getTimestamp(); // 2nd try (the type in the modal

    $constraints[] = $query->lessThanOrEqual('entrydate', $today);
    $constraints[] = $query->equals('deleted', 0, false);


        ->matching(
                $query->logicalAnd($constraints)
            )
            ->setLimit(10)
            ->setOrderings(array(
                    'entrydate' => \TYPO3\CMS\Extbase\Persistence\QueryInterface::ORDER_DESCENDING
                )
            );

    // Some debug's to find out more. sadly didn't work
    \TYPO3\CMS\Core\Utility\DebugUtility::debug( $today , 'today value');
    \TYPO3\CMS\Core\Utility\DebugUtility::debug( $query, 'my query');
    \TYPO3\CMS\Core\Utility\DebugUtility::debug( $constraints, 'constraints');

    $result = $query->execute();




?>

所以:有人对如何调试它有好的建议吗? Whosebug 上的一个人在另一个主题中写了一个条目解释我们只需要在 TYPO3 中打开 sql 错误并在查询中输入错误的值以输出 sql 错误。这可行,但错误消息不会持续到我尝试比较的字段。所以如果s.b,我会很高兴。会帮助我摆脱这种痛苦。

旧式调试在 8.x 中不再有效,否则这没什么大不了的。

    <?php 
            $parser =        \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\CMS\Extbase\Persistence\Generic\Storage\Typo3DbQueryParser');
            $parser->convertQueryToDoctrineQueryBuilder($query);
            $queryParts = $parser->parseQuery($query);
            \TYPO3\CMS\Core\Utility\DebugUtility::debug($queryParts, 'Query');
    ?>

顺便说一下,该模型...在我使用它的所有部分都运行良好,但存储库中的自定义查询除外。

    /**
    * entrydate
    *
    * @var \DateTime
    */
    protected $entrydate = null;

我也搜索了 Whosebug,但没有找到合适的解决方案。 - 对我来说,这个不起作用: How to compare DateTime in Extbase repository - 我不会用这个查询:How to debug a query in extbase? - 这也没有:Extbase - get created sql from query

事实上,TYPO3从TYPO3 v8开始使用Doctrine作为它的连接,你可以使用Doctrine SQLLoggers来调试你的查询,这是一个非常简单的任务。

/**
 * Description of EntityRepository
 *
 * @author Kevin Ditscheid <kevinditscheid@gmail.com>
 */
class EntityRepository extends \TYPO3\CMS\Extbase\Persistence\Repository{
    /**
     * Find entities by a given DateTime object
     *
     * @param \DateTime $date The DateTime to filter by
     *
     * @return \TYPO3\CMS\Extbase\Persistence\QueryResultInterface
     */
    public function findByDate(\DateTime $date): \TYPO3\CMS\Extbase\Persistence\QueryResultInterface{
        $query = $this->createQuery();
        $queryResult = $query->matching($query->greaterThan('timestampDate', $date))->execute();

        // create a new logger for the database queries to log
        $logger = new \Doctrine\DBAL\Logging\EchoSQLLogger();
        // get the Docrine Connection configuration object
        $connectionConfiguration = $this->getConnectionPool()->getConnectionForTable('tx_sqldebug_domain_model_entity')->getConfiguration();
        // backup the current logger
        $loggerBackup = $connectionConfiguration->getSQLLogger();
        // set our logger as the active logger object of the Doctrine connection
        $connectionConfiguration->setSQLLogger($logger);
        // we need to fetch our results here, to enable doctrine to fetch the results
        $entities = $queryResult->toArray();
        // restore the old logger
        $connectionConfiguration->setSQLLogger($loggerBackup);
        return $queryResult;
    }
    /**
     * Get the ConnectionPool object
     *
     * @return \TYPO3\CMS\Core\Database\ConnectionPool
     */
    protected function getConnectionPool(): \TYPO3\CMS\Core\Database\ConnectionPool{
        return \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Core\Database\ConnectionPool::class);
    }
}

此示例获取 TYPO3 ConnectionPool 对象,该对象存储 TYPO3 正在使用的数据库连接。然后它获取我们要处理的 table 的特定连接对象并获取其配置对象,该对象本身是 class \Doctrine\DBAL\Configuration 的一个实例。现在它可以将自己的 SQLLogger 实例附加到配置对象。它使用 Doctrine \Doctrine\DBAL\Logging\EchoSQLLogger 简单地 var_dumps 查询。它备份和恢复 Configuration 的 Logger 对象,只是为了不丢失任何东西,以后的查询不会 var_dumped 并且用不必要的声音淹没输出。 您现在应该可以看到使用 extbase 查询对象创建的查询。

我在这里为 TYPO3 8 创建了一个小示例扩展:https://github.com/the-coding-owl/sql_debug

根据 https://docs.typo3.org/typo3cms/TCAReference/ColumnsConfig/Type/Input.html#id25 Typo3 将您的 DateTime 对象动态转换为 Unix 时间戳。

因此,在生成的 SQL 请求中,WHERE 子句会将 Unix 时间戳与日期对象进行比较...这就像将苹果与香蕉进行比较一样,结果一无所获。

我没有找到一种方法可以将日期对象存储在数据库中并将它们与自定义存储库进行比较,因为 'eval' 参数是必需的并将所有内容转换为时间戳。

解决方案是将您的日期信息也作为时间戳存储在数据库中。

要在自定义数据库查询中处理 DateTime 对象,您应该将其用作字符串:

$query->lessThan('modified_on', $date->format('Y-m-d H:i:s')

这在 TYPO3 v8.7.7 中对我有用,有这个修复的错误: https://forge.typo3.org/issues/81056