Как отсортировать метод findAll Doctrine

77

Я читал документацию Doctrine, но мне не удалось найти способ поиска findAll() Results.

Я использую symfony2 + doctrine, это утверждение, которое я использую внутри моего контроллера:

$this->getDoctrine()->getRepository('MyBundle:MyTable')->findAll();

но я хочу, чтобы результаты упорядочивались по возрастанию имен пользователей.

Я пытаюсь передать массив как аргумент следующим образом:

findAll( array('username' => 'ASC') );

но он не работает (он тоже не жалуется).

Есть ли способ сделать это, не создавая DQL-запрос?

Теги:
doctrine2

10 ответов

159
Лучший ответ

Как @Lighthart, как показано, да, возможно, хотя он добавляет значительный жир к контроллеру и не является СУХОЙ.

Вы действительно должны определить свой собственный запрос в репозитории объектов, это простая и лучшая практика.

use Doctrine\ORM\EntityRepository;

class UserRepository extends EntityRepository
{
    public function findAll()
    {
        return $this->findBy(array(), array('username' => 'ASC'));
    }
}

Затем вы должны указать своей сущности искать запросы в репозитории:

/**
 * @ORM\Table(name="User")
 * @ORM\Entity(repositoryClass="Acme\UserBundle\Entity\Repository\UserRepository")
 */
class User
{
    ...
}

Наконец, в вашем контроллере:

$this->getDoctrine()->getRepository('AcmeBundle:User')->findAll();
  • 1
    Это лучший подход, чем мой, но вы будете писать dql; мой метод имеет меньше dql и поэтому отвечает ограничению OP. Честно говоря, страх перед dql должен быть просто преодолен. Используйте этот метод вместо моих, если это возможно.
  • 0
    ну, это не страх перед dql, и перед прочтением этого ответа я в конечном итоге использовал DQL для достижения этой цели, но я не хотел использовать DQL вначале, потому что в моем контроллере не было DQL, и я хотел придерживаться Стиль кода, который уже был у контроллера. Это решение работает очень хорошо для меня!
Показать ещё 6 комментариев
52
$this->getDoctrine()->getRepository('MyBundle:MyTable')->findBy([], ['username' => 'ASC']);
  • 0
    Это простое решение.
  • 0
    очень простое решение, спасибо striiig
13

Полезно иногда смотреть на исходный код.

Например, реализация findAll очень проста (vendor/doctrine/orm/lib/Doctrine/ORM/EntityRepository.php):

public function findAll()
{
    return $this->findBy(array());
}

Итак, мы смотрим на findBy и находим то, что нам нужно (orderBy)

public function findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
6

Простой:

$this->getDoctrine()->getRepository('AcmeBundle:User')->findBy(
    array(),
    array('username' => 'ASC')
);
  • 0
    Это работает как шарм! И до сих пор работает именно так с Symfony 4
5

Вам нужно использовать критерии, например:

<?php

namespace Bundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Doctrine\Common\Collections\Criteria;

/**
* Thing controller
*/
class ThingController extends Controller
{
    public function thingsAction(Request $request, $id)
    {
        $ids=explode(',',$id);
        $criteria = new Criteria(null, <<DQL ordering expression>>, null, null );

        $rep    = $this->getDoctrine()->getManager()->getRepository('Bundle:Thing');
        $things = $rep->matching($criteria);
        return $this->render('Bundle:Thing:things.html.twig', [
            'entities' => $things,
        ]);
    }
}
4

Посмотрите на исходный код API Doctrine:

class EntityRepository{
  ...
  public function findAll(){
    return $this->findBy(array());
  }
  ...
}
4

Это работает для меня:

$entities = $em->getRepository('MyBundle:MyTable')->findBy(array(),array('name' => 'ASC'));

Сохранение первого пустого массива возвращает все данные, он работал в моем случае.

2

Попробуйте следующее:

$em = $this->getDoctrine()->getManager();

$entities = $em->getRepository('MyBundle:MyTable')->findBy(array(), array('username' => 'ASC'));
2

Я использую альтернативу решению, которое написало nifr.

$resultRows = $repository->fetchAll();
uasort($resultRows, function($a, $b){
    if ($a->getProperty() == $b->getProperty()) {
        return 0;
    }
    return ($a->getProperty()< $b->getProperty()) ? -1 : 1;
});

Это быстрее, чем предложение ORDER BY, и без накладных расходов на Iterator.

  • 1
    Это сработало для меня!
2

Вы можете отсортировать существующий массив ArrayCollection с помощью итератора массива.

Предполагая, что $collection является вашим ArrayCollection, возвращаемым findAll()

$iterator = $collection->getIterator();
$iterator->uasort(function ($a, $b) {
    return ($a->getPropery() < $b->getProperty()) ? -1 : 1;
});
$collection = new ArrayCollection(iterator_to_array($iterator));

Это можно легко превратить в функцию, которую вы можете поместить в свой репозиторий, чтобы создать метод findAllOrderBy().

  • 4
    Какой у вас смысл здесь? Для этого более чем достаточно сценариев использования ... т.е. сортировка уже извлеченной коллекции в PHP всегда быстрее, чем выполнение другого запроса mysql только для сортировки! Представьте, что вам нужно вывести одни и те же данные коллекции в двух разных стилях сортировки на одной странице ...
  • 2
    В общем, возвращение упорядоченного запроса должно быть задачей базы данных. OTOH, эта техника действительно применима к более сложным случаям, о которых ни упоминает.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню