2012-09-10 19 views
5

Doctrine2リスナー&私は、適用されているエンティティでうまく動作する、未承認/草案のエンティティを除外する手段として機能するフィルタを持っていますが、関係のためにそれを動作させる方法はわかりません。関係に基づいてDoctrine2フィルタを実装するにはどうすればよいですか?

商品についてfindBy()を実行すると、エンティティがカテゴリと呼ばれ、そのカテゴリに関連する商品があるとします。関連するカテゴリが承認されているかどうかを確認するクエリが必要です。

select * from products p
left join category c on p.category_id = c.id
where p.id = 5and c.approved = true

太字のビットが私のフィルタまたは同等によって注入される必要があるものです。

これを実装するにはどうすればよいですか?

は、これまでのところ私は、フィルタ内のどこの一環として注入されたサブクエリを持っているが、これは地獄のようだ、と私はより良い方法がなければならないと思っています:

class ApprovableFilter extends SQLFilter 
{ 
    protected $listener; 
    protected $entityManager; 

    public function addFilterConstraint(ClassMetadata $targetEntity, $targetTableAlias) 
    { 
     $config = $this->getListener()->getConfiguration($this->getEntityManager(), $targetEntity->name); 

     /* this bit works fine for the category */ 

     if (isset($config['approvable']) && $config['approvable']) { 
      $column = $targetEntity->columnNames[$config['fieldName']]; 

      return $targetTableAlias.'.'.$column.' = true'; 
     } 

     /* this bit works for products.. but seems like a pretty poor solution */ 

     if (isset($targetEntity->associationMappings['category'])) { 
      $config = $this->getListener()->getConfiguration(
       $this->getEntityManager(), 
       $targetEntity->associationMappings['category']['targetEntity'] 
      ); 

      return '(
       select d.id from dealership d 
       where d.id = '.$targetTableAlias.'.dealership_id 
       and d.'.$config['fieldName'].' = true 
      ) is not null'; 
     } 
    } 
+0

あなたがやっていることが一番良いようです。リクエストにすでにJOINが含まれている場合は、どうしますか? – AdrienBrault

+0

@AdrienBraultもう一度結合をやり直すと同時に、エイリアスが理論的に矛盾する可能性がありますが、これを行うには私が試したことよりも良い方法があるはずですそれをやり遂げる方法を知りません。 – Steve

答えて

1

私は考えることができる最高Categoryオブジェクトを介して商品を検索することです。
このようにすると、category.approvedフィールドをフィルタリングするだけで済みます。例えば

public function addFilterConstraint(ClassMetadata $targetEntity, $targetTableAlias) 
{ 
    $config = $this->getListener()->getConfiguration($this->getEntityManager(), $targetEntity->name); 

    /* this bit works fine for the category */ 

    if (isset($config['approvable']) && $config['approvable']) { 
     $column = $targetEntity->columnNames[$config['fieldName']]; 

     return $targetTableAlias.'.'.$column.' = true'; 
    } 
} 

その後、あなたのカテゴリーエンティティは(あなたが双方向関係を持っていると仮定して)製品のコレクションを持っている必要があります。

use Doctrine\Common\Collections\ArrayCollection; 

class Category { 
    /** 
    * @var ArrayCollection $products 
    * @ORM\OneToMany(targetEntity="Product", mappedBy="category") 
    */ 
    private $products; 

    public function __construct() 
    { 
     $this->products = new ArrayCollection; 
    } 

    public function getProducts() 
    { 
     return $this->products; 
    } 
} 

あなたが最初にあなたのカテゴリー

$category = $this->get('doctrine')->getRepository('SomeBundle:Category')->find(5); 
if($category) { 
    //Here you now the category is approved 
    $products = $category->getProducts(); 
} 

を取得することができますこの方法は、このことができます願っています。

編集:

@lracicot質問に答えると、一方向の関係のための例を与える: 私は例えばProjectRepository方法作成します。

... 
findByCategoryApproved($product_id, $approved = true) 
{ 
    $query = 
     'SELECT p 
     FROM AcmeBundle:Product 
     LEFT JOIN p.categories c 
     WHERE p.id = :id AND c.approved = :approved'; 

    return $this 
     ->getEntityManager() 
     ->createQuery($query) 
     ->setParameter('id', $product_id) 
     ->setParameter('approved', $approved) 
     ->getOneOrNullResult(); 
} 

を...

$product = $doctrine 
    ->getRepository('AcmeBundle:Product') 
    ->findByCategoryApproved(5); 
+0

私は同様の問題がありますが、私の場合、 "Product"から "Category"への関係は単方向であるため、 "Category"から "Products"を得ることはできません。あなたはその場合何を提案しますか? – lracicot

+1

@lracicot私の答えを見る編集;) – Gintro

関連する問題