2013-06-13 4 views
16

Symfony 2のベストプラクティスに関する質問があります。申し訳ありませんが、少し曖昧で主観的です。私は私の質問を以下のようにまとめることができると思います:Symfonyのベストプラクティス。クエリはリポジトリまたはサービスにあるべきですか?

"リポジトリはいつも問い合わせのために適切な場所ですか?"

今は私の主義のクエリのほとんどをエンティティリポジトリに入れています。私のコントローラのアクションのほとんどは、エンティティまたはエンティティのコレクションのクエリのような典型的なことを行い、例外を投げたり、その結果に応じてリダイレクトしたり、そうでなければ1つ以上のエンティティを更新したりします。ほとんどのアクションは、standard - > find、 - > findByなどのクエリで効率的に行うよりも複雑です。ほとんどの場合、結合が必要です。クエリに複数のエンティティが含まれている場合、どのリポジトリに入るべきかわからないことがあります。クエリのルートエンティティがあると思いますが...時には結合エンティティのデータがより重要で関連性が高いので間違っていると感じますルートエンティティのリポジトリに格納します。

これは問題なく動作していますが、リポジトリ内ではほとんど同じだがわずかに異なるクエリに遭遇する傾向があります。名前を思いついて、それぞれが何をしているのかを正確に把握すると、混乱し退屈になる可能性があります。これらのクエリの大半は、同じコントローラ内の1つまたは2つ(たいていはあまり使用されないことが多い)のコントローラアクションによってのみ使用されます。私はあまりにも多くの専門的な、まれに使用されたもので私のリポジトリを混乱させているように感じる。

最も単純なアクション以外は、オブジェクトやサービスにカプセル化する必要があります。だから、私はリポジトリではなくサービスで直接多くの質問をし始めました。アクションを一箇所で見るのは簡単です。これは大丈夫でしょうか?

+1

コントローラーは、アプリケーションの世界とhttpの世界の間の本当に薄いレイヤーでなければならず、常にリポジトリーにクエリーを置くことを推奨します。 –

答えて

9

あなたのクエリは簡単に再利用のことができるようにするために、あなたのコントローラであなたのエンティティリポジトリずに保管してください。

これは、リポジトリが実際に行っていることです。データベースクエリに再利用可能な場所を提供する。

ただし、リポジトリ内のすべてのクエリを保持することができます...特に、フィルタリングに関しては、すばやく多くのクエリが必要な場合があります。

Benjamin Eberlei(Doctrineの作成者)は、クラス内の5つのパブリックメソッドが大丈夫であるとみなし、10がかなり大きいとみなします。彼は最近、彼のブログに「On Taming Repository Classes in Doctrine」という興味深い記事を掲載しています。

私は部分的には、KnpLabsのフィルタリング可能なリポジトリの特性解答がDoctrineBehaviorsで好きです。

形質は難しいテストを作るが、あなたはクリーナーを持つことができ、あなたのクエリをおくべき場所に簡単リポジトリ ... を維持します。

+2

リンクをありがとう、両方とも面白いです。私は私のコントローラにクエリを入れるつもりはありませんでした。私はちょうど類似しているが全く同じ名前ではなく、全く同じクエリをたくさん似たようなもので私のリポジトリを膨らませない方法を模索しています。 – tetranz

9

あなたは何かを行うことができます。コードの再利用を可能にしながら、

use Doctrine\ORM\EntityManager; 
use Doctrine\ORM\EntityRepository; 

class PostManager 
{ 
    protected $em; 

    protected $repo; 

    protected $class; 

    public function __construct(EntityManager $em, $class) { 
     $this->em = $em; 
     $this->class = $class; 
     $this->repo = $em->getRepository($class); 
    } 

    public function get($id) 
    { 
     return $this->repo->findById($id); 
    } 
} 

この方法では、あなたはまだリポジトリに、彼らが属しているクエリを、残すことができます:

blog.post_manager: 
    class: Acme\BlogBundle\Entity\Manager\PostManager 
    arguments: 
     em: "@doctrine.orm.entity_manager" 
     class: Acme\BlogBundle\Entity\Post 

が続いマネージャークラスを作成します。

サービスを定義します。

$this->container->get('blog.post_manager')->get(1); 

このサービスは、クラスとエンティティマネージャをManagerクラスに注入するためのアイスクリームが必要になります。これにより、コントローラのシンナーが保持され、モデルから遠ざけることができます。

+1

+1のマネージャークラスは良いヒントですが、実際の質問はどこにクエリを保存するかということでした。ほとんどの場合リポジトリにする必要があります。マネージャークラスは、データベースにアクセスするさまざまな方法を抽象化するという利点を提供します。エンティティリポジトリを使用するマネージャクラスを1つ、ドキュメントリポジトリを使用して別のストレージバックエンドを使用することができます。それらがすべて同じインターフェイスを実装している限り、コントローラで交換することができます。それはつまり、FOSUserBundleがdoctrine orm、odm、propelを処理する方法です:) – nifr

+1

"この方法では、リポジトリに属する​​クエリを残すことができます[...]" –

+0

ああ、そこに隠れて、 – nifr

関連する問題