TYPO3 Order by Random im Repository

Oder auch: Datensätze in zufälliger Reihenfolge ausgeben

Es kommt schonmal vor, dass man Datensätze aus dem Repository in zufälliger Reihenfolge ausgeben möchte. In meinem Fall habe ich Kundenzitate und möchte sie gerne zufällig sortiert in einem Slider ausgeben. Meine Recherche ergab, dass ORDER BY RAND() nicht geht seit Doctrine in TYPO3 eingezogen ist, diverse Links zu Diskussionen hier und da. Ich bin stur: es muss doch gehen. Da habe ich diesen Forumsbeitrag entdeckt, wo jemand es mit TypoScript hinbekommen hat, in TYPO3 8 wohlgemerkt. Da TypoScript ja auch von Doctrine verarbeitet wird, geht es also doch, man muss nur etwas um die Ecke denken.

Meine Lösung sieht wie folgt aus: Query mit Doctrine zusammenbauen, zusätzliches Feld einfügen das einen Zufallswert enthält und nachdem sortiert wird, Ergebnisse holen und mit dem DataMapper in Objekte transformieren.

use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Core\Database\Query\Restriction\FrontendRestrictionContainer;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper;
/**
 * @param int $limit
 */
public function findRandom($limit)
{
    $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($this->getTableName());
    $queryBuilder->setRestrictions(GeneralUtility::makeInstance(FrontendRestrictionContainer::class));
    $records = $queryBuilder
        ->select('*')
        ->addSelectLiteral('rand() AS random_sort')
        ->from($this->getTableName())
        ->orderBy('random_sort')
        ->setMaxResults($limit)
        ->execute()
        ->fetchAll();
    $dataMapper = GeneralUtility::makeInstance(DataMapper::class);
    $result = $dataMapper->map($this->objectType, $records);
    return $result;
}
 
/**
 * Return the current tablename
 *
 * @return string
 */
protected function getTableName()
{
    $dataMapper = GeneralUtility::makeInstance(DataMapper::class);
    $tableName = $dataMapper->getDataMap($this->objectType)->getTableName();
    return $tableName;
}

Funktionert wunderbar in TYPO3 8.7.

2 Kommentare

  1. Juri Kostik

    Ich habe bis jetzt ähnlichen Code für eigene Querys verwendet, aber in der TYPO3 v.9.5.4 funktioniert es nicht mehr. Man erhält folgende Fehlermeldung: „Call to a member function buildDataMap() on null“. Wissen Sie vielleicht woran es liegen kann bzw. wie man queryBuilder mit mapping auf eigene Klassen nutzen kann?

    Vielen Dank im Voraus!

  2. Hallo Juri,

    ich hatte die selbe Fehlermeldung und konnte es beheben, in dem ich den DataMapper über den ObjectManager hole.

    $objectManager = GeneralUtility::makeInstance(\TYPO3\CMS\Extbase\Object\ObjectManager::class);
    $dataMapper = $objectManager->get(\TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper::class);