Feature #14026

Add new ordering "RAND()" to TYPO3 DB Backend

Added by Kai Vogel about 4 years ago. Updated 5 months ago.

Status:New Start date:2011-03-24
Priority:Should have Due date:
Assigned To:- % Done:

0%

Category:Extbase Spent time: -
Target version:7.1 (Cleanup)
PHP Version: Sprint Focus:
Complexity:

Description

Currently the only allowed sort modes are ascending (ASC) and descending (DESC), but there is no way to order by RAND, which will return a random result set. The only possibility to do that is, to create a native SQL statement and lose the abstraction from a concrete storage backend.

See:
Tx_Extbase_Persistence_Storage_Typo3DbBackend::parseOrderings()


Related issues

blocks news extension - Feature #56903: Offer "sort by random" On Hold 2014-03-14

History

#1 Updated by Michael McManus almost 4 years ago

  • Has patch set to No

#2 Updated by Ingo Pfennigstorf over 2 years ago

  • Status changed from New to Needs Feedback
  • Target version deleted (Extbase 1.4)

As the JCR specification that we follow here [1] does not have a RAND or other random ordering and ORDER BY RAND is very MySQL specific (see [2]) I would suggest to reject this feature. What do you think?

[1] http://www.day.com/specs/jcr/1.0/6.6.3.5_Ordering_Specifier.html
[2] http://www.petefreitag.com/item/466.cfm

#3 Updated by Stefan Neufeind over 2 years ago

I agree we need some solution that can be used across various DBMS. Thanks for the links.

But we should have random-sorting in some way. So I agree with you that simply using RAND and forgetting about other DBMS is not a solution. But I disagree with you in regards to rejecting this feature-request itself.

#4 Updated by Ingo Pfennigstorf over 2 years ago

This is how Doctrine (FLOW3) solved it (not).
http://www.doctrine-project.org/jira/browse/DDC-950

And this is an easy way to implement it in a custom query (german)
http://typo3blogger.de/random-record-repository/

#5 Updated by Stefan Neufeind over 2 years ago

Yey, so that's what an ORM is for: Telling you it doesn't care about the database-specific stuff and only leaves creating a custom (DB-dependent solution) as your only option.

The custom repository works in a way. But if you need more rows it even gets a bit more hacky. (Yes you could do a fetch where uid in (...) and shuffle them inside php). So exactly that "custom solution" that everybody needing a RAND will have to write himself is not really an option imho.

Now if Doctrine doesn't want to help, and if Extbase needs to find a way to do it that FLOW3 will be fine with as well, what's our option? Put database-dependent stuff inside Extbase/FLOW3 since Doctrine doesn't want to care about it? Hmm ...

#6 Updated by Anja Leichsenring almost 2 years ago

  • Target version set to Extbase 6.3

#7 Updated by Maximilian Kalus about 1 year ago

I agree with Stefan: In real world scenarios, sometimes you would need a rand-function. Simply telling me, that your ORM does not support it, does not help.

Up to TYPO3 6.1, one could work with a simple workaround (described in http://typo3blogger.de/random-record-repository/ - my comment from 27.03.2014 ). In 6.2, buildQuery is not exposed any more, so you cannot hack the SQL statement any more. Honestly, this is a negative development. I can understand convertig statements to work smoothly with models, etc., but to close off query building completely to a developer is a grevious mistake! In my 10 years of TYPO3 developing, I often had to implement very specific queries for customers (from imports, weird sources, etc.), randomized queries being a relatively common task (and no, shuffling 5000 records in PHP is not an option, sorry!). In TYPO3 6.2, my only option for this is using plain old $GLOBALS['TYPO3_DB'] - seriously?

Please fix this!

#8 Updated by Daniel Siepmann 11 months ago

Another workaround is to extend the Typo3DbQueryParser like the following.

It's just a workaround that allows rand() but can be extended e.g. to support any function that configured.

<?php

namespace CUSTOM\CustomHelpers\Persistence\Generic\Storage;

use TYPO3\CMS\Extbase\Persistence\Generic\Storage\Typo3DbQueryParser;
use TYPO3\CMS\Extbase\Persistence\Generic\Qom;

/**
 * Extend Typo3DbQueryParser to support some MySQL features.
 *
 * As we only use MySQL we can use MySQL features inside our queries,
 * even if we build them using the query factory of Extbase.
 *
 * @author Daniel Siepmann <daniel.siepmann@typo3.org>
 * @since 6.2
 */
class CustomDbQueryParser extends Typo3DbQueryParser {

    /**
     * Extend default parsing to allow rand() explicity.
     *
     * @param array $orderings An array of orderings (Qom\Ordering)
     * @param Qom\SourceInterface $source The source
     * @param array &$sql The query parts
     * @throws \TYPO3\CMS\Extbase\Persistence\Generic\Exception\UnsupportedOrderException
     * @return void
     *
     * @author Daniel Siepmann <daniel.siepmann@typo3.org>
     */
    protected function parseOrderings( array $orderings, Qom\SourceInterface $source, array &$sql ) {
        parent::parseOrderings( $orderings, $source, $sql );
        if (count( $sql['orderings'] ) === 0) {
            return;
        }

        foreach ($sql['orderings'] as $orderingKey => $ordering) {
            $positionOfRandom = stripos( $sql['orderings'][0], 'rand()' );
            if ($positionOfRandom !== false) {
                $sql['orderings'][$orderingKey] = substr( $ordering, $positionOfRandom );
            }
        }
    }

}

Just register the cutom parser in the ext_localconf.php:

if (TYPO3_branch !== '4.7') {
    // Overwrite the Dependency Injection for Typo3DbQueryParser.
    // @since 6.2
    \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance( '\\TYPO3\\CMS\\Extbase\\Object\\Container\\Container' )
            ->registerImplementation(
                'TYPO3\CMS\Extbase\Persistence\Generic\Storage\Typo3DbQueryParser',
                'CUSTOM\CustomHelpers\Persistence\Generic\Storage\CustomDbQueryParser'
            );
}

#9 Updated by Alexander Opitz 8 months ago

  • Project changed from Extbase MVC Framework to Core
  • Category changed from Extbase: Generic Persistence to Extbase
  • Status changed from Needs Feedback to New
  • Target version changed from Extbase 6.3 to 7.0

#10 Updated by Mathias Schreiber 5 months ago

  • Target version changed from 7.0 to 7.1 (Cleanup)

Also available in: Atom PDF