findAll Doctrineのメソッドをソートする方法


111

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

私はsymfony2 + doctrineを使用しています、これは私のコントローラー内で使用しているステートメントです:

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

しかし、私は結果をユーザー名の昇順で並べ替えたいです。

私はこの方法で配列を引数として渡そうとしました:

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

しかし、機能しません(文句も言われません)。

DQLクエリを作成せずにこれを行う方法はありますか?

回答:


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

まあそれはdqlを恐れているわけではなく、この回答を読む前に最終的にDQLを使用してこれを達成しましたが、コントローラーにはDQLが含まれていないため、最初はDQLを使用したくありませんでした。コントローラがすでに持っていたコードスタイル。この解決策は私にとって本当にうまくいきます!
ILikeTacos 2013年

1
または単に:$ this-> getDoctrine()-> getRepository( 'AcmeBundle:User')-> findBy(array()、array( 'username' => 'ASC'));
Benji_X80 2014年

1
@ Benji_X80そのワンライナーは確かに短いですが、それはまったくDRYではありません。findAllメソッドは、コントローラではなくリポジトリに属します。
Pier-Luc Gendreau、2014年

1
コメントを使用する以外の方法でカスタムリポジトリでクエリを検索するようエンティティに指示できますか?これは私が今まで見た中で最もひどいプログラミング慣行です
Sejanus

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

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());
  }
  ...
}

このコードスニペットは何も並べ替えません
ニコ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,
        ]);
    }
}

4

symfonyのfindByメソッドは2つのパラメータを除いています。1つ目は検索するフィールドの配列、2つ目は並べ替えフィールドとその順序です

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

非常に短い答えに説明を追加できますか?
Nico Haase

それは強力な短い答えです。精巧-説明... 編集
ポールホッジス

それは完璧な答えでした!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クエリを実行するよりも常に高速です。...あなたは出力1つのページ上の2つの異なるソートスタイルで同じコレクションのデータを必要と想像して
ニコライフレーリッヒ

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句よりも高速で、イテレータのオーバーヘッドがありません。


回答にさらに説明を追加してください。アプリケーションでの並べ替えは、データベースレベルで行うよりもどのように速くできますか?
Nico Haase

0

EntityRepositoryのデフォルトのfindAll関数を次のように変更します。

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

そうすれば、クエリを並べ替えるオプションを使用して、任意のデータテーブルの任意のクエリで '' findAll ''を使用できます

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.