2013-08-09 8 views
8

the Doctrine Docsに従って基準を設定しようとしています。Doctrine 2.3基準。関連するオブジェクトへのアクセス

残念ながら、関連するオブジェクトの属性にアクセスする方法は教えていません。私に例を挙げてみましょう。

私は製品のArrayCollectionを持っています。すべての製品にカテゴリーがあります。カテゴリ名のArrayCollectionをフィルタリングする必要があります。今、私は次のように条件を設定しようとしています:

$criteria = Criteria::create() 
    ->where(Criteria::expr()->eq("category.name", "SomeCategoryName")); 

今、私は次の例外を取得:私は、関連するオブジェクトにアクセスするにはどうすればよい

An exception has been thrown during the rendering of a template ("Unrecognized field: category.name") 

を?

答えて

5

私はソースコードCriteria::expr()->eq("name", --- second value ---)を調べました。 2番目の値は、Doctrine\Common\Collections\Expr\Valueのインスタンスを想定しています。したがって、Exprまたはcriteriaをそこに入れることはできません。 ExprAndおよびOrのみが別のExprをとります。 filter()のような他の関数でこれを解決するか、またはgetIterator()でイテレータを取得すると思います。これはfilter()メソッドを使って行うことができます。

$filteredProducts = 
    $products->filter(function($key, $element) use ($categoryName) { 
     return $element->getCategory()->getName() === categoryName; 
    }); 

もしすることができますあなたがそれらの内部にネストforeach文やフィルタをすることができ、それぞれ次の関係についてIterator

+1

ありがとうございました。私はあなたの 'Ctriteria'を月曜日にテストします。今は私のワークステーションにアクセスできない。それが動作すれば私はあなたに知らせます。しかし、フィルタはすべてのカテゴリーが熱心に読み込まれ、ディスク上でローカルに処理されるため、私の考えでは悪い考えです(DB上で行うよりもパフォーマンスが悪くないでしょう)。 – Robin

+0

あなたは間違っています。 Criteriaは、クエリー(フェッチされるデータ)とArrayCollection(すでにフェッチされたデータ)で使用できます。フェッチ・ジョインを作成しなかった場合は、criteriaまたはfilter()を使用するかどうかにかかわらず、リレーションは熱心にロードされます。あなたはDBがあなたに最高のパフォーマンスを与えるので、WHEREとの組み合わせでフェッチ結合を使用するのが最良です。それはあなたの質問についてではありませんでしたが。 – Flip

+0

エンティティに注釈を付けることができると思って、遅延ロードされていると思いますか? http:// docs。doctrine-project.org/en/2.0.x/reference/annotations-reference.html#annref-manytoone。 'ArrayCollection'レイジーをロードしないでしょうか?それが逆のアノテーションなので、それはうまくいかないでしょうか? – Robin

2

おそらくフィルタメソッドではなく、リポジトリメソッドに属している可能性があります。親オブジェクトのコレクション(Orderなど)のフィルタリング済みリストを取得したい場合は、クエリビルダーで子コレクションをフィルタリングできます。しかし、完全に水和した物を持たないという混乱する可能性のある副作用に対処する必要があります。

オブジェクトのリストを表示する必要があります。カテゴリ名に一致する子供はProductしかありません。

class OrderRepository extends EntityRepository { 
    public function findOrderWithProductCategory($category) 
    { 
    $builder = $this->createQueryBuilder('o') 
     ->select('o, p') 
     ->leftJoin('o.products', 'p') 
     ->join('p.category', 'c', 'WITH', 'c.name = :category') 
     ->setParameter('category', $category); 
    } 
} 

あなたは後で、あなたはおそらく、より良いとにかく@フリップのソリューションを使用している、とすべてのカテゴリを事前に水和するまで興味を持っているカテゴリの種類がわからない場合。 partial hydrationと標準ArrayCollection::filter()のクロージャを使用すると、ほとんどの場合、かなり良好に動作します。

しかし、それは機能としては素晴らしいと言えます。現在のCriteriaの実装は非常に軽量であり、おそらくそれをそのままにしたいと考えているため、Doctrineの人たちは嫌なものだと思う。

+0

実際、この[issue](https://github.com/doctrine/collections/pull/27)は既に開かれています: – yvoyer

関連する問題