如何排序findAll主义的方法


111

我一直在阅读Doctrine的文档,但无法找到对findAll()结果进行排序的方法。

我正在使用symfony2 +准则,这是我在Controller内使用的语句:

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

但我希望结果按用户名升序排列。

我一直试图通过这种方式将数组作为参数传递:

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

但它不起作用(也不会抱怨)。

有没有建立DQL查询的方法?

Answers:


229

如图所示,如@Lighthart所示,是可以的,尽管它为控制器增加了很多脂肪,并且不是DRY。

您实际上应该在实体存储库中定义自己的查询,这是简单且最佳实践。

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 2014年

1
@ Benji_X80虽然单线肯定更短,但它根本不是干的。findAll方法属于存储库,而不是控制器。
2014年

1
您是否可以让实体以除使用注释以外的任何其他方式在自定义存储库中查找查询?这是我所见过的最糟糕的编程习惯
Sejanus 2014年

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


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

您需要使用一个条件,例如:

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

Symfony中的findBy方法除外两个参数。第一个是要搜索的字段数组,第二个是排序字段及其顺序

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

您可以在简短回答中添加一些解释吗?
Nico Haase

这是一个简短的答案。详细说明- 编辑
Paul Hodges

那是完美的答案!findBy(array(),array('fieldname'=>'ASC')这将查找所有内容并按指示的方向对字段进行排序
Robert Saylor

2

您可以使用数组迭代器对现有ArrayCollection进行排序。

假设$ collection是findAll()返回的ArrayCollection

$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查询要快!想象一下,您需要在一页上以两种不同的排序样式输出相同的集合数据...
NicolaiFröhlich

2
通常,返回有序查询应该是数据库的工作。OTOH,此技术确实适用于nifr提及的更多涉案案件。
Lighthart 2014年

2

试试这个:

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

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

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

修改EntityRepository中的默认findAll函数,如下所示:

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

这样,您可以对任何数据表的任何查询使用“ findAll”,并带有对查询进行排序的选项

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.