2013-06-14 49 views
79

私はDoctrineのドキュメントを読んできましたが、findAll()の結果をソートする方法を見つけることができませんでした。findAll Doctrineのメソッドをソートする方法

私はSymfony2の+教義を使用しています、これは私が私のコントローラ内で使用している文です:

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

が、私は結果がユーザ名を昇順で注文することにしたいです。

私は、引数として、このように配列を渡すしようとしてきた。(それはどちらか文句はありません)

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

が、それは動作しません。

DQLクエリを作成せずにこれを行う方法はありますか?あなたは、たとえば、基準を使用する必要が

答えて

158

示すように、はい、それは、可能です。

実際にエンティティリポジトリに独自のクエリを定義する必要があります。これは単純でベストプラクティスです。

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(); 
+1

これは私より優れたアプローチですが、あなたはdqlを書くでしょう。私のメソッドは、より少ないSQLを持っているので、OPの制約に答えます。率直に言って、dqlに対する恐怖は克服すべきです。可能であれば、この方法を優先的に使用してください。 – Lighthart

+0

これはdqlの恐怖ではなく、この答えを読む前に私は最終的にこれを達成するためにDQLを使用しましたが、私のコントローラーにはDQLがないのでDQLを使いたくなかったので、コントローラが既に持っていたコードスタイル。このソリューションは私にとって本当にうまく機能します! – ILikeTacos

+1

@ Pier-Luc Gendreauとてもシンプルでスマートです:) – pregmatch

5

:それはコントローラに重要な脂肪を追加し、DRYはないが@Lighthartとして

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

あなたは、配列を使用して、既存のArrayCollectionを並べ替えることができますイテレータ。

これは、簡単にあなたがfindAllOrderBy()メソッドを作成するためにあなたのリポジトリに置くことができる機能に変換することができます

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

)$コレクションはのfindAll(によって返さあなたのArrayCollectionであると仮定。

+4

を参照してくださいここにポイント?これには十分なユースケースがあります。つまり、PHPですでにフェッチされたコレクションをソートすることは、並べ替えのために別のmysqlクエリを実行するよりも常に高速です! 1つのページに2つの異なるソートスタイルで同じコレクションデータを出力する必要があるとします。 – nifr

+2

一般に、順序付けられたクエリを返すのはデータベースのジョブでなければなりません。 OTOHでは、この技法はより多くの場合にnifrの言及に適用可能である。 – Lighthart

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

このソリューションは簡単です。 –

+0

非常に簡単な解決策、ありがとうstriiig –

2

私はnifrを書いた解決策の代わりに使用します。

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

それは BY句ORDERよりも高速だし、イテレータのオーバーヘッドなし。

+1

それは私のために働いた! –

4

これは私の作品:

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

空が戻って、すべてのデータをフェッチする最初の配列を維持する、それが私の場合で働いていました。

2

これを試してみてください:

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

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

それは時々、ソースコードを見て便利です。

例えばfindAll実装は非常に簡単です(vendor/doctrine/orm/lib/Doctrine/ORM/EntityRepository.php):教義APIのソース・コードで

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

だから我々はfindByを見て、私たちは(orderBy)必要なものを見つける

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

ルック:

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

シンプル:

$this->getDoctrine()->getRepository('AcmeBundle:User')->findBy(
    array(), 
    array('username' => 'ASC') 
); 
関連する問題