TYPO3 8.x Сравнение даты и времени в CustomRepository (запрос, ограничения)

Я пытаюсь настроить свой запрос, используя поле сравнения в репозитории TYPO3, и не совсем понимаю. Кто-нибудь знает, как правильно отладить это? Я использую CMS TYPO3 8.x. (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();




?>

Итак: есть ли у кого-нибудь хороший совет, как это отлаживать? Один парень из stackoverflow написал запись в другой теме, объясняющую, что нам просто нужно включить ошибки sql в TYPO3 и ввести ошибочное значение в запросе, чтобы вывести ошибку sql. Это сработает, но сообщение об ошибке не распространяется на поле, которое я пытаюсь сравнить. Так что я был бы очень рад, если бы с.б. поможет мне выбраться из этой беды.

Отладка старой школы больше не работает в 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;

Я также искал stackoverflow, но не нашел подходящего решения. - Для меня это не работает: Как сравнить DateTime в репозитории Extbase - я не получу свой запрос с этим: Как отлаживать запрос в extbase? - также не делал этого: Extbase - получить созданный sql из запроса


person Manuel Thaler    schedule 22.04.2017    source источник
comment
Вы нашли решение? Я застрял в том же месте. Получил отладочную информацию из SQLLogger, но кажется, что заполнитель подготовленного состояния не заполнен для даты и времени: SELECT tx_my_domain_model_event.* FROM tx_my_domain_model_event tx_my_domain_model_event WHERE (tx_my_domain_model_event.startdate › :dcValue1) AND (tx_my_domain_model_event.sys_language_uid IN (0, -1)) И (tx_my_domain_model_event.pid IN (10, 11, 12, 13, 17, 19, 20, 26)) И... поэтому сравнение даты и времени выполняется против: dcValue1   -  person Jøran    schedule 04.05.2017


Ответы (3)


В соответствии с тем фактом, что TYPO3 использует Doctrine в качестве соединения, начиная с TYPO3 v8, вы можете использовать Doctrine SQLLoggers для отладки ваших запросов, что является очень простой задачей.

/**
 * Description of EntityRepository
 *
 * @author Kevin Ditscheid <[email protected]>
 */
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. Затем он получает конкретный объект Connection для таблицы, с которой мы хотим работать, и получает ее объект Configuration, который сам является экземпляром класса \Doctrine\DBAL\Configuration. Теперь он может присоединять собственный экземпляр SQLLogger к объекту конфигурации. Он использует Doctrine \Doctrine\DBAL\Logging\EchoSQLLogger, которая просто var_dumps запросы. Он создает резервную копию и восстанавливает объект Logger конфигурации, просто для сохранения ничего не потеряно, и последующие запросы не будут var_dumped и не будут заливать вывод ненужным голосом. Теперь вы должны увидеть запросы, которые вы создали с помощью объекта запроса extbase.

Я создал небольшой пример расширения для TYPO3 8 здесь: https://github.com/the-coding-owl/sql_debug

person Euli    schedule 22.04.2017
comment
Какое отличное расширение!!! Кевин, это просто великолепно! Спасибо за очень быстрый и компетентный ответ! - person Manuel Thaler; 26.04.2017

Для обработки объектов DateTime в пользовательских запросах datatabse вы должны использовать его как строку:

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

Это работает для меня в TYPO3 v8.7.7 с этой исправленной ошибкой: https://forge.typo3.org/issues/81056

person TOS    schedule 06.10.2017

Согласно https://docs.typo3.org/typo3cms/TCAReference/ColumnsConfig/Type/Input.html#id25 Typo3 динамически преобразует ваши объекты DateTime в метки времени Unix.

Таким образом, в результирующем SQL-запросе предложение WHERE будет сравнивать временную метку Unix с объектом Date... Это похоже на сравнение яблок с бананами и ни к чему не приводит.

Я не нашел способа, как вы можете хранить Date-объекты в базе данных и сравнивать их с пользовательским репозиторием, потому что параметр «eval» требуется и преобразует все в временные метки.

Решением было бы также хранить информацию о вашей дате в виде метки времени в базе данных.

person JoBalk    schedule 05.05.2017