วิธีการเรียงลำดับวิธีการของ findAll Doctrine?


112

ฉันได้อ่านเอกสารของ 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 น้อยกว่าจึงตอบข้อ จำกัด ของ OP ตรงไปตรงมาควรเอาชนะความกลัว dql ใช้วิธีนี้ตามความต้องการในการขุดถ้าเป็นไปได้
Lighthart

ไม่ต้องกลัว dql และก่อนที่จะอ่านคำตอบนี้ในที่สุดฉันก็ใช้ DQL เพื่อให้บรรลุสิ่งนี้ แต่ฉันไม่ต้องการใช้ DQL ในตอนแรกเพราะคอนโทรลเลอร์ของฉันไม่มี DQL อยู่เลยและฉันต้องการยึดติดกับ รูปแบบรหัสที่คอนโทรลเลอร์มีอยู่แล้ว วิธีนี้ใช้ได้ผลดีกับฉันจริงๆ!
ILikeTacos

1
หรือเพียงแค่: $ this-> getDoctrine () -> getRepository ('AcmeBundle: User') -> findBy (array (), array ('username' => 'ASC'));
Benji_X80

1
@ Benji_X80 แม้ว่าซับเดียวนั้นจะสั้นกว่า แต่ก็ไม่แห้งเลย เมธอด findAll เป็นของที่เก็บไม่ใช่คอนโทรลเลอร์
Pier-Luc Gendreau

1
คุณสามารถบอกให้เอนทิตีค้นหาแบบสอบถามในที่เก็บแบบกำหนดเองด้วยวิธีอื่นนอกเหนือจากการใช้ความคิดเห็นได้หรือไม่ เป็นการฝึกเขียนโปรแกรมที่แย่ที่สุดที่ฉันเคยเห็น
Sejanus


24

ง่าย:

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

สิ่งนี้ได้ผลอย่างมีเสน่ห์! และยังคงทำงานในลักษณะนี้กับ Symfony 4
Robert Saylor

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

ดูซอร์สโค้ด Doctrine API:

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

ข้อมูลโค้ดนี้ไม่ได้เรียงลำดับอะไรเลย
Nico Haase

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,
        ]);
    }
}

5

วิธี findBy ใน Symfony ยกเว้นสองพารามิเตอร์ อันดับแรกคืออาร์เรย์ของฟิลด์ที่คุณต้องการค้นหาและอาร์เรย์ที่สองคือฟิลด์การเรียงลำดับและลำดับ

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

คุณช่วยเพิ่มคำอธิบายให้กับคำตอบสั้น ๆ ของคุณได้ไหม
Nico Haase

นั่นเป็นคำตอบสั้น ๆ ที่ทรงพลัง ละเอียด - อธิบาย ... แก้ไข .
Paul Hodges

นั่นคือคำตอบที่สมบูรณ์แบบ! findBy (array (), array ('fieldname' => 'ASC') สิ่งนี้จะค้นหาทั้งหมดและจัดเรียงบนฟิลด์ตามทิศทางที่ระบุ
Robert Saylor

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 อื่นสำหรับการเรียงลำดับเสมอ! ลองนึกภาพว่าคุณต้องส่งออกข้อมูลคอลเลกชันเดียวกันในรูปแบบการจัดเรียงที่แตกต่างกันสองแบบในหน้าเดียว ...
Nicolai Fröhlich

2
โดยทั่วไปการส่งคืนแบบสอบถามที่สั่งซื้อควรเป็นงานของฐานข้อมูล OTOH เทคนิคนี้มีผลบังคับใช้กับกรณีที่เกี่ยวข้องมากขึ้นที่กล่าวถึง nifr
Lighthart


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


โปรดเพิ่มคำอธิบายเพิ่มเติมในคำตอบของคุณ การเรียงลำดับในแอปพลิเคชันของคุณจะเร็วกว่าการจัดเรียงในระดับฐานข้อมูลได้อย่างไร
Nico Haase

0

แก้ไขฟังก์ชัน findAll เริ่มต้นใน EntityRepository ดังนี้:

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

ด้วยวิธีนี้คุณสามารถใช้ '' findAll '' ในแบบสอบถามสำหรับตารางข้อมูลใดก็ได้โดยมีตัวเลือกในการจัดเรียงแบบสอบถาม

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.