Як сортувати метод findAll Doctrine


111

Я читав документацію Doctrine, але не зміг знайти спосіб сортування результатів findAll ().

Я використовую symfony2 + доктрину, це твердження, яке я використовую всередині мого контролера:

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

але я хочу, щоб результати були упорядковані за зростанням імен користувачів.

Я намагався передати масив як аргумент таким чином:

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

але це не працює (теж не скаржиться).

Чи можна це зробити без створення запиту DQL?

Відповіді:


229

Як на @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();

2
Це кращий підхід, ніж мій, але ви будете писати dql; мій метод має менше dql і тому відповідає обмеженню ОП. Чесно кажучи, страх перед dql слід просто подолати. Використовуйте цей метод, віддаючи перевагу моєму, якщо це можливо.
Лайтхарт

добре, це не боїться dql, і перш ніж прочитати цю відповідь, я в кінцевому рахунку використовував DQL для досягнення цього, але я не хотів використовувати DQL на початку, тому що в моєму контролері не було жодного DQL, і я хотів дотримуватися стиль коду, який контролер вже мав. Це рішення працює дуже добре для мене!
ILikeTacos

1
Або просто: $ this-> getDoctrine () -> getRepository ('AcmeBundle: користувач') -> findBy (array (), array ('ім'я користувача' => 'ASC'));
Benji_X80

1
@ Benji_X80 Хоча цей одноводковий звичайно коротший, він взагалі НЕ СУХИЙ. Метод findAll належить до сховища, а не до контролера.
П’єр-Люк Джендро

1
Чи можете ви сказати суб'єкту господарювання шукати запити в спеціальному сховищі будь-яким іншим способом, ніж використання коментарів? Це найстрашніша практика програмування, яку я коли-небудь бачив
Sejanus



20

Іноді корисно дивитися на вихідний код.

Наприклад, 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

Це працює для мене:

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

Зберігаючи порожній масив першого масиву назад всі дані, він працював у моєму випадку.



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

метод findBy в Symfony перевищує два параметри. Перший - це масив полів, за якими потрібно шукати, а другий масив - це поле сортування та його порядок

public function findSorted()
    {
        return $this->findBy(['name'=>'Jhon'], ['date'=>'DESC']);
    }

Чи можете ви додати якесь пояснення до своєї дуже короткої відповіді?
Ніко Хааз

Це могутня коротка відповідь. Розробити - пояснити ... відредагувати .
Пол Ходжес

це була ідеальна відповідь! findBy (array (), array ('fieldname' => 'ASC') Це знайде всіх і сортувати на полі із вказаним напрямком
Robert Saylor

2

Ви можете сортувати існуючий ArrayCollection за допомогою ітератора масиву.

припускаючи, що колекція $ - це ваш 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 лише для сортування! Уявіть, що вам потрібно вивести однакові дані колекції у двох різних стилях сортування на одній сторінці ...
Nicolai Fröhlich

2
Взагалі повернення впорядкованого запиту повинно бути завданням бази даних. Щодо іншого, ця методика може застосовуватися до більш задіяних випадків, про які йдеться.
Лайтхарт

2

Спробуйте це:

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

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

1

Я використовую альтернативу рішенню, яке написав 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.


Будь ласка, додайте додаткові пояснення до своєї відповіді. Як сортування у вашій програмі може бути швидшим, ніж робити це на рівні бази даних?
Ніко Хааз

0

Змініть функцію findAll за замовчуванням у EntityRepository так:

public function findAll( array $orderBy = null )
{
    return $this->findBy([], $orderBy);
}

Таким чином, ви можете використовувати '' findAll '' у будь-якому запиті для будь-якої таблиці даних з можливістю сортування запиту.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.