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?

ILikeTacos
sumber

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();
Pier-Luc Gendreau
sumber
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']);
Stiig
sumber
24

Sederhana:

$this->getDoctrine()->getRepository('AcmeBundle:User')->findBy(
    array(),
    array('username' => 'ASC')
);
Daniele Dolci
sumber
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)
luchaninov
sumber
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.

Buttler
sumber
5

Lihat kode sumber API Doktrin:

class EntityRepository{
  ...
  public function findAll(){
    return $this->findBy(array());
  }
  ...
}
Gilles Vanderstraeten
sumber
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,
        ]);
    }
}
Lighthart
sumber
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']);
    }
Shaz
sumber
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 ().

Nicolai Fröhlich
sumber
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'));
Mahdi Dhifi
sumber
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.

Moisés Márquez
sumber
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

niksa
sumber