Bagaimana mengurutkan metode findAll Doctrine


111

Saya telah membaca dokumentasi Doctrine, tetapi saya belum dapat menemukan cara untuk mengurutkan Hasil findAll ().

Saya menggunakan doktrin symfony2 +, ini adalah pernyataan yang saya gunakan di dalam Controller saya:

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

tapi saya ingin hasil diurutkan dengan menaik nama pengguna.

Saya telah mencoba untuk melewatkan sebuah array sebagai argumen dengan cara ini:

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

tetapi tidak berhasil (juga tidak mengeluh).

Apakah ada cara untuk melakukan ini tanpa membuat kueri DQL?

Jawaban:


229

Seperti @Lighthart seperti yang ditunjukkan, ya itu mungkin, meskipun menambahkan lemak yang signifikan ke pengontrol dan tidak KERING.

Anda harus benar-benar menentukan kueri Anda sendiri di repositori entitas, ini sederhana dan praktik terbaik.

use Doctrine\ORM\EntityRepository;

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

Kemudian Anda harus memberi tahu entitas Anda untuk mencari kueri di repositori:

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

Terakhir, di pengontrol Anda:

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

2
Ini adalah pendekatan yang lebih baik daripada saya, tetapi Anda akan menulis dql; metode saya memiliki lebih sedikit dql sehingga menjawab kendala OP. Terus terang, ketakutan akan dql seharusnya diatasi. Gunakan metode ini sebagai preferensi untuk menambang jika memungkinkan.
Lighthart

baik itu bukan takut dql, dan sebelum membaca jawaban ini saya akhirnya menggunakan DQL untuk mencapai ini, tetapi saya tidak ingin menggunakan DQL pada awalnya karena pengontrol saya tidak memiliki DQL di dalamnya, dan saya ingin tetap menggunakan gaya kode yang sudah dimiliki pengontrol. Solusi ini bekerja sangat baik untuk saya!
ILikeTacos

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

1
@ Benji_X80 Meskipun garis satu itu lebih pendek, tidak KERING sama sekali. Metode findAll milik repositori, bukan pengontrol.
Pier-Luc Gendreau

1
Bisakah Anda memberi tahu entitas untuk mencari kueri di repositori kustom dengan cara lain selain menggunakan komentar? Ini praktik pemrograman paling mengerikan yang pernah saya lihat
Sejanus

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

24

Sederhana:

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

Ini bekerja dengan sangat baik! Dan masih berfungsi persis seperti ini dengan Symfony 4
Robert Saylor

20

Terkadang berguna untuk melihat kode sumber.

Misalnya findAllimplementasinya sangat sederhana ( vendor/doctrine/orm/lib/Doctrine/ORM/EntityRepository.php):

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

Jadi kami melihat findBydan menemukan apa yang kami butuhkan ( orderBy)

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

6

Ini bekerja untuk saya:

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

Menjaga array pertama kosong mengambil kembali semua data, itu berhasil dalam kasus saya.


5

Lihat kode sumber API Doktrin:

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

Potongan kode ini tidak menyortir apa pun
Nico Haase

5

Anda perlu menggunakan kriteria, misalnya:

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

Metode findBy di Symfony mengecualikan dua parameter. Pertama adalah array bidang yang ingin Anda cari dan array kedua adalah bidang sortir dan urutannya

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

Bisakah Anda menambahkan penjelasan untuk jawaban singkat Anda?
Nico Haase

Itu jawaban singkat yang kuat. Rumit - jelaskan ... edit .
Paul Hodges

itu jawaban yang sempurna! findBy (array (), array ('fieldname' => 'ASC') Ini akan menemukan semua dan mengurutkan di lapangan dengan arah yang ditunjukkan.
Robert Saylor

2

Anda dapat mengurutkan ArrayCollection yang ada menggunakan iterator array.

dengan asumsi $ collection adalah ArrayCollection Anda yang dikembalikan oleh findAll ()

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

Ini dapat dengan mudah diubah menjadi fungsi yang dapat Anda masukkan ke dalam repositori Anda untuk membuat metode findAllOrderBy ().


4
Apa maksudmu disini? Ada lebih dari cukup kasus penggunaan untuk ini ... yaitu menyortir koleksi yang sudah diambil di PHP selalu lebih cepat daripada melakukan kueri mysql lain hanya untuk menyortir! Bayangkan Anda perlu mengeluarkan data koleksi yang sama dalam dua gaya pengurutan yang berbeda pada satu halaman ...
Nicolai Fröhlich

2
Secara umum, mengembalikan kueri yang dipesan harus menjadi tugas database. OTOH, teknik ini benar-benar dapat diterapkan pada kasus-kasus yang lebih terlibat yang disebutkan sebelumnya.
Lighthart

2

Coba ini:

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

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

1

Saya menggunakan alternatif solusi yang menulis nifr.

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

Ini lebih cepat daripada klausa ORDER BY , dan tanpa overhead Iterator.


Harap tambahkan beberapa penjelasan lebih lanjut untuk jawaban Anda. Bagaimana pengurutan dalam aplikasi Anda bisa lebih cepat daripada melakukannya di tingkat database?
Nico Haase

0

Ubah fungsi findAll default di EntityRepository seperti ini:

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

Dengan begitu Anda dapat menggunakan '' findAll '' pada kueri apa pun untuk tabel data apa pun dengan opsi untuk mengurutkan kueri tersebut

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.