Как получить случайную строку с помощью Doctrine2 querybuilder?

#symfony #doctrine-orm

#symfony #doctrine-orm

Вопрос:

Пока у меня есть:

 $qb1 = $this->getEntityManager()->createQueryBuilder();
            $qb1->select('s')
                ->from('MyEntitySong', 's')
                ->where('s.id <> ?1')
                ->orderBy('RAND()', '')
                ->setMaxResults(1)
                ->setParameters(array(1=>$current->id));
  

Но doctrine2 этого не понимает:

 Error: Expected end of string, got '('
  

Даже на их странице querybuilder ничего нет. Вы хотите сказать мне, что лучший ORM для php не имеет функции random?

Комментарии:

1. Здесь и здесь приведены два примера из Doctrine 1.2. Я бы предположил, что нечто подобное сработало бы для Doctrine 2.

Ответ №1:

Метод OrderBy должен принимать поле песни для целей сортировки (например, ‘s.author’ или ‘s.title’), а не случайное значение. Даже если вы выбрали случайное поле для упорядочивания, например, произвольно выбрали одно в php, это будет совсем не случайным, потому что вы всегда будете получать первый результат по текущим критериям сортировки. Если в ваших песнях 8 полей, вы получите только 8 разных песен в результатах поиска, даже если у вас хранятся тысячи.

Вот предложение:

 $qb1->select('s')
    ->from('MyEntitySong', 's')
    ->where('s.id <> ?1')
    ->setMaxResults(1)
    ->setParameters(array(1=>$current->id))
    ->setFirstResult($offset);
  

Здесь $offset может быть случайным значением, которое вы получаете в php с помощью функций rand () или mt_rand(). Конечно, $offset должно быть меньше общего количества песен. Это всего лишь предложение, есть много способов, которыми вы можете это сделать.

ИМХО, я думаю, Doctrine2 — это необычный ORM, и нет ничего более продвинутого, чем он. Я предполагаю, что вы прочитали раздел справочного руководства о построителе запросов, но я также предлагаю вам прочитать раздел о DQL, в котором объясняется, какие функции доступны в системе запросов Doctrine, и как вы можете создать свои собственные (!).

Комментарии:

1. Настолько необычно, что вы не можете просто ЗАКАЗАТЬ С помощью RAND ().

Ответ №2:

Вам нужно добавить пользовательскую функцию DQL RAND. Для платформы symfony2 вы могли бы просто добавить в config:

 doctrine:
    orm:
        entity_managers:
            default:
                dql:
                    numeric_functions:
                        rand: DoctrineExtensionsQueryMysqlRand
  

И добавить к вам зависимости в composer.json:

composer require beberlei/DoctrineExtensions

Тогда решение для получения 100 случайных AcmeBundle:Item объектов было бы таким простым, как:

 $em = $this->getContainer()->get('doctrine')->getManager();
$messages = $em->createQueryBuilder()
    ->select('i, RAND() AS HIDDEN r')
    ->from('AcmeBundle:Item', 'i')
    ->orderBy('r', 'ASC')
    ->setMaxResults(100)
    ->getQuery()
    ->getResult();
  

Примечание: предполагается, что вы используете серверную часть MySQL или MariaDB. Для SQLite или PostgreSQL вам может понадобиться другой класс реализации.