So sortieren Sie die Methode von findAll Doctrine


110

Ich habe die Dokumentation von Doctrine gelesen, aber ich konnte keine Möglichkeit finden, findAll () -Ergebnisse zu sortieren.

Ich verwende die Symfony2 + -Doktrin. Dies ist die Aussage, die ich in meinem Controller verwende:

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

Ich möchte jedoch, dass die Ergebnisse nach aufsteigenden Benutzernamen sortiert werden.

Ich habe versucht, ein Array folgendermaßen als Argument zu übergeben:

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

aber es funktioniert nicht (es beschwert sich auch nicht).

Gibt es eine Möglichkeit, dies zu tun, ohne eine DQL-Abfrage zu erstellen?

Antworten:


228

Wie bei @Lighthart gezeigt, ist dies möglich, obwohl es dem Controller erheblich Fett hinzufügt und nicht trocken ist.

Sie sollten wirklich Ihre eigene Abfrage im Entitäts-Repository definieren, es ist einfach und bewährte Methode.

use Doctrine\ORM\EntityRepository;

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

Anschließend müssen Sie Ihre Entität anweisen, im Repository nach Abfragen zu suchen:

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

Schließlich in Ihrem Controller:

$this->getDoctrine()->getRepository('AcmeBundle:User')->findAll();

2
Dies ist ein besserer Ansatz als meiner, aber Sie werden dql schreiben; Meine Methode hat weniger dql und entspricht damit der Einschränkung des OP. Ehrlich gesagt sollte die Angst vor dql einfach überwunden werden. Verwenden Sie diese Methode nach Möglichkeit lieber als meine.
Lighthart

Nun, es ist keine Angst vor DQL, und bevor ich diese Antwort gelesen habe, habe ich letztendlich DQL verwendet, um dies zu erreichen, aber ich wollte DQL am Anfang nicht verwenden, weil mein Controller kein DQL darin hatte, und ich wollte mich an das halten Codestil, den der Controller bereits hatte. Diese Lösung funktioniert wirklich gut für mich!
ILikeTacos

1
Oder einfach: $ this-> getDoctrine () -> getRepository ('AcmeBundle: User') -> findBy (array (), array ('username' => 'ASC'));
Benji_X80

1
@ Benji_X80 Während dieser Einzeiler sicherlich kürzer ist, ist er überhaupt nicht trocken. Die findAll-Methode gehört zum Repository, nicht zum Controller.
Pier-Luc Gendreau

1
Können Sie die Entität anweisen, auf andere Weise als mithilfe von Kommentaren nach Abfragen im benutzerdefinierten Repository zu suchen? Es ist die schrecklichste Programmierpraxis, die ich je gesehen habe
Sejanus

81
$this->getDoctrine()->getRepository('MyBundle:MyTable')->findBy([], ['username' => 'ASC']);

24

Einfach:

$this->getDoctrine()->getRepository('AcmeBundle:User')->findBy(
    array(),
    array('username' => 'ASC')
);

Das hat wie ein Zauber gewirkt! Und funktioniert immer noch genau so mit Symfony 4
Robert Saylor

20

Manchmal ist es nützlich, sich den Quellcode anzusehen.

Zum Beispiel ist die findAllImplementierung sehr einfach ( vendor/doctrine/orm/lib/Doctrine/ORM/EntityRepository.php):

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

Also schauen wir uns an findByund finden, was wir brauchen ( orderBy)

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

6

Das funktioniert bei mir:

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

Wenn das erste Array leer bleibt, werden alle Daten abgerufen, in meinem Fall hat es funktioniert.


5

Schauen Sie sich den Doctrine API-Quellcode an:

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

Dieses Code-Snippet sortiert nichts
Nico Haase

5

Sie müssen ein Kriterium verwenden, zum Beispiel:

<?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

Die findBy-Methode in Symfony akzeptiert zwei Parameter. Das erste ist ein Array von Feldern, nach denen Sie suchen möchten, und das zweite Array ist das Sortierfeld und seine Reihenfolge

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

Können Sie Ihrer sehr kurzen Antwort eine Erklärung hinzufügen?
Nico Haase

Das ist eine mächtige kurze Antwort. Ausarbeiten - erklären ... bearbeiten .
Paul Hodges

das war die perfekte antwort! findBy (array (), array ('fieldname' => 'ASC') Hiermit werden alle gefunden und auf dem Feld mit der angegebenen Richtung sortiert.
Robert Saylor

2

Sie können eine vorhandene ArrayCollection mithilfe eines Array-Iterators sortieren.

Angenommen, $ collection ist Ihre ArrayCollection, die von findAll () zurückgegeben wird.

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

Dies kann leicht in eine Funktion umgewandelt werden, die Sie in Ihr Repository einfügen können, um die Methode findAllOrderBy () zu erstellen.


4
Was ist dein Punkt hier? Es gibt mehr als genug Anwendungsfälle dafür ... dh das Sortieren einer bereits abgerufenen Sammlung in PHP ist immer schneller als das Ausführen einer anderen MySQL-Abfrage nur zum Sortieren! Stellen Sie sich vor, Sie müssen dieselben Sammlungsdaten in zwei verschiedenen Sortierstilen auf einer Seite ausgeben ...
Nicolai Fröhlich

2
Im Allgemeinen sollte die Rückgabe einer geordneten Abfrage Aufgabe der Datenbank sein. OTOH, diese Technik ist auf die involvierteren Fälle anwendbar, die nicht erwähnt werden.
Lighthart

2

Versuche dies:

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

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

1

Ich benutze eine Alternative zu der Lösung, die nifr geschrieben hat.

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

Es ist schneller als die ORDER BY- Klausel und ohne den Overhead des Iterators.


Bitte fügen Sie Ihrer Antwort eine weitere Erklärung hinzu. Wie kann das Sortieren in Ihrer Anwendung schneller sein als auf Datenbankebene?
Nico Haase

0

Ändern Sie die Standardfunktion findAll in EntityRepository wie folgt:

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

Auf diese Weise können Sie '' findAll '' für jede Abfrage für eine beliebige Datentabelle verwenden und die Abfrage sortieren

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.