2016-05-10 15 views
0

現在、複数の言語をサポートするSymfony 3を使用して電子商取引サイトを構築しています。 /翻訳、商品レビュー、割引/スペシャルオファーなどを読み込むためのクエリビルダ。しかし、これは、複数のリポジトリで同じになる結合ブロックを持つつもりであることを意味します。これは、余分に読み込むために結合を追加または変更する必要がある場合は、これらのブロックをすべて捜す必要があるためです。製品データ。複数のアソシエーションを持つdoctrineエンティティのロード方法を修正する方法

私はこのようなDQLクエリを持っている私のCartRepositoryのloadCart()関数の中で例えば:私は、そのページ上の製品のリストを示していたときに

SELECT c,i,p,pd,pt,ps FROM 
AppBundle:Cart c 
join c.items i 
join i.product p 
left join p.productDiscount pd 
join p.productTranslation pt 
left join p.productSpecial ps 
where c.id = :id 

私はSectionRepositoryで似たようになってしまいますこれに対処する正しい方法は何ですか?参加エンティティ(ここではProduct)が完了するためにロードする必要があるエンティティのリストを集中的に定義できる場所がありますか?私はちょうど遅延読み込みを使用することができたが、それはセクションページのようなページ上で実行されている大量のクエリにつながるだろうと考えています(40個の製品を示すセクションで、上記の例では121個のクエリを実行する必要があります。正しく結合されたクエリ)。

答えて

1

1つのアプローチ(これは私の頭の上からちょうど離れている、誰かがより良いアプローチを持つかもしれない)。あなたは合理的に簡単に、それを行うセントラルクエリビルダ機能/サービスを持つことができます。 querybuilderは、プログラムによるクエリの構築に非常に適しています。主な違いは、ルートエンティティとフィルタリングエンティティです。

など。このようなもの。もちろん、これらはすべて同じ場所にあるわけではありません(いくつかのサービス、リポジトリなどにまたがっているかもしれません)。これは単なる考慮する方法の例です。

public function getCartBaseQuery($cartId, $joinAlias = 'o') { 

    $qb = $this->getEntityManager()->createQueryBuilder(); 

    $qb->select($joinAlias) 
     ->from('AppBundle:Cart', 'c') 
     ->join('c.items', $joinAlias) 
     ->where($qb->expr()->eq('c.id', ':cartId')) 
     ->setParameter('cartId', $cartId); 

    return $qb; 
} 

public function addProductQueryToItem($qb, $alias) { 

    /** @var QueryBuilder $query */ 
    $qb 
     ->addSelect('p, pd, pt, ps') 
     ->join($alias.'product', 'p') 
     ->leftJoin('p.productDiscount', 'pd') 
     ->join('p.productTranslation', 'pt') 
     ->join('p.productSpecial', 'ps') 
    ; 

    return $qb; 
} 


public function loadCart($cartId) { 

    $qbcart = $someServiceOrRepository->getCartBaseQuery($cartId); 
    $qbcart = $someServiceOrRepository->addProductQueryToItem($qbcart); 

    return $qbcart->getQuery()->getResult(); 
} 

私は、ただ一つの可能​​なアプローチを言ったが、うまくいけば、それはあなたにいくつかのアイデアや問題を解決するために開始を与えると同様。

注:エンティティに宗教的に同じ結合エイリアスを使用する場合は、商品データを添付することで通話で指定する必要はありません(ただし、自分で設定することができます)。

1

あなたの質問に対して1つの正解はありません。

しかし、私が提案しなければならないのは、CQRS(http://martinfowler.com/bliki/CQRS.html)を見てみると、基本的に分離した読み込みモデルがあるということです。

これを可能な限り簡単にするには、すべてのデータが既に結合され、正規化解除されている別の「拡張プロダクト」テーブルを作成するとします。この表には、一定の間隔でバックグラウンド・タスクが設定されているか、製品または関連するエンティティーを更新するたびにトリガーされるコマンドによって入力されます。

製品データを読む必要がある場合は、元のテーブルの代わりにこのテーブルをクエリします。もちろん、データを別の方法で並べ替えて多数の異なる拡張テーブルを作成することはできません。それはことを除いてデータベース「ビュー」に非常によく似た概念、だいくつかの方法で

  • あなたは、実際のテーブル
  • を照会するので、それはあなたがコードを介して、そのテーブルを作成するので、あなたは、高速であります

これは正確に「回答」ではありませんが、うまくいけば、どのようにしてデータを処理するかについての良いアイデアを与えるかもしれません。あなたの問題を解決してください。

関連する問題