Cách sắp xếp phương thức findAll Doctrine


111

Tôi đã đọc tài liệu của Doctrine, nhưng tôi không thể tìm ra cách sắp xếp các kết quả findAll ().

Tôi đang sử dụng học thuyết symfony2 +, đây là câu lệnh mà tôi đang sử dụng bên trong Bộ điều khiển của mình:

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

nhưng tôi muốn các kết quả được sắp xếp theo tên người dùng tăng dần.

Tôi đã cố gắng chuyển một mảng làm đối số theo cách này:

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

nhưng nó không hoạt động (nó cũng không phàn nàn).

Có cách nào để làm điều này mà không cần xây dựng truy vấn DQL không?

Câu trả lời:


229

Như @Lighthart như được hiển thị, có, nó có thể, mặc dù nó thêm chất béo đáng kể vào bộ điều khiển và không KHÔ.

Bạn thực sự nên xác định truy vấn của riêng mình trong kho thực thể, đó là phương pháp đơn giản và tốt nhất.

use Doctrine\ORM\EntityRepository;

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

Sau đó, bạn phải yêu cầu thực thể của mình tìm kiếm các truy vấn trong kho lưu trữ:

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

Cuối cùng, trong bộ điều khiển của bạn:

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

2
Đây là một cách tiếp cận tốt hơn của tôi, nhưng bạn sẽ viết dql; phương pháp của tôi có ít dql hơn và do đó trả lời hạn chế của OP. Thành thật mà nói, sợ hãi về dql chỉ nên được vượt qua. Sử dụng phương pháp này tùy ý để khai thác nếu có thể.
Lighthart

Vâng, nó không sợ dql, và trước khi đọc câu trả lời này, cuối cùng tôi đã sử dụng DQL để đạt được điều này, nhưng tôi không muốn sử dụng DQL ngay từ đầu vì bộ điều khiển của tôi không có bất kỳ DQL nào trong đó và tôi muốn sử dụng kiểu mã mà bộ điều khiển đã có. Giải pháp này thực sự hiệu quả đối với tôi!
ILikeTacos

1
Hoặc đơn giản hơn: $ this-> getDoctrine () -> getRepository ('AcmeBundle: User') -> findBy (array (), array ('username' => 'ASC'));
Benji_X80

1
@ Benji_X80 Mặc dù một lớp lót đó chắc chắn ngắn hơn, nhưng nó không KHÔ chút nào. Phương thức findAll thuộc về kho lưu trữ, không thuộc về bộ điều khiển.
Pier-Luc Gendreau

1
Bạn có thể yêu cầu thực thể tìm kiếm các truy vấn trong kho lưu trữ tùy chỉnh theo bất kỳ cách nào khác ngoài việc sử dụng nhận xét không? Đó là thực hành lập trình khủng khiếp nhất mà tôi từng thấy
Sejanus

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

24

Đơn giản:

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

Điều này hoạt động như một sự quyến rũ! Và vẫn hoạt động chính xác theo cách này với Symfony 4
Robert Saylor

20

Đôi khi, việc xem xét mã nguồn sẽ rất hữu ích.

Ví dụ, findAllviệc triển khai rất đơn giản ( vendor/doctrine/orm/lib/Doctrine/ORM/EntityRepository.php):

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

Vì vậy, chúng tôi xem xét findByvà tìm những gì chúng tôi cần ( orderBy)

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

6

Điều này phù hợp với tôi:

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

Giữ mảng trống đầu tiên tìm nạp lại tất cả dữ liệu, nó hoạt động trong trường hợp của tôi.


5

Xem mã nguồn API Doctrine:

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

Đoạn mã này không sắp xếp bất cứ thứ gì
Nico Haase

5

Bạn cần sử dụng một tiêu chí, ví dụ:

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

Phương thức findBy trong Symfony loại trừ hai tham số. Đầu tiên là mảng trường bạn muốn tìm kiếm và mảng thứ hai là trường sắp xếp và thứ tự của nó

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

Bạn có thể thêm một số giải thích cho câu trả lời rất ngắn của bạn?
Nico Haase

Đó là một câu trả lời ngắn gọn. Công phu - giải thích ... sửa .
Paul Hodges

đó là câu trả lời hoàn hảo! findBy (array (), array ('fieldname' => 'ASC') Điều này sẽ tìm thấy tất cả và sắp xếp trên trường với hướng được chỉ định.
Robert Saylor

2

Bạn có thể sắp xếp một ArrayCollection hiện có bằng cách sử dụng một trình lặp mảng.

giả sử $ collection là ArrayCollection của bạn được trả về bởi findAll ()

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

Điều này có thể dễ dàng được chuyển thành một hàm mà bạn có thể đưa vào kho lưu trữ của mình để tạo phương thức findAllOrderBy ().


4
Ý bạn ở đây là gì? Có quá nhiều trường hợp sử dụng cho việc này ... tức là sắp xếp một tập hợp đã được tìm nạp trong PHP luôn nhanh hơn thực hiện một truy vấn mysql khác chỉ để sắp xếp! Hãy tưởng tượng bạn cần để sản xuất các dữ liệu thu thập cùng một trong hai phong cách sắp xếp khác nhau trên một trang ...
Nicolai Fröhlich

2
Nói chung, trả về một truy vấn có thứ tự phải là công việc của cơ sở dữ liệu. OTOH, kỹ thuật này có khả năng áp dụng cho nhiều trường hợp liên quan hơn mà nifr đề cập.
Lighthart

2

Thử cái này:

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

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

1

Tôi sử dụng một giải pháp thay thế cho giải pháp đã viết nifr.

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

Nó nhanh hơn mệnh đề ORDER BY và không có chi phí của lặp lại.


Vui lòng thêm một số giải thích thêm cho câu trả lời của bạn. Làm thế nào việc sắp xếp trong ứng dụng của bạn có thể nhanh hơn so với việc sắp xếp ở cấp độ cơ sở dữ liệu?
Nico Haase

0

Sửa đổi hàm findAll mặc định trong EntityRepository như thế này:

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

Bằng cách đó, bạn có thể sử dụng '' findAll '' trên bất kỳ truy vấn nào cho bất kỳ bảng dữ liệu nào với tùy chọn sắp xếp truy vấn

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.