2012-09-10 1 views
5

Doctrine2 리스너 & 필터는 승인되지 않은/초안 엔티티를 필터링하는 수단으로 사용되며 적용된 엔티티에서 제대로 작동하지만 그 관계에 대해 작동시키는 방법을 알지 못합니다 .관계를 기반으로 Doctrine2 필터를 구현하려면 어떻게해야합니까?

엔티티를 카테고리라고 부르며 제품에 대해 findBy()을 수행 할 때 해당 카테고리와 관련된 제품이 있다고 가정하면 관련된 카테고리가 승인되었는지 확인해야합니다.

굵게 표시된 비트 and c.approved = true

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

내 또는 동등한 필터에 의해 분사 될 필요하다.

어떻게 구현할 수 있습니까?

은 지금까지 나는 필터의 경우의 일환으로 주입 하위 쿼리가 있지만,이 지옥 같은 것, 그리고 더 좋은 방법이있을 생각 해요 :

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.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

비슷한 문제가 있지만 제 경우에는 "제품"에서 "범주"로의 관계가 단방향이기 때문에 "범주"에서 "제품"을 가져올 수 없습니다. 이 경우 당신은 무엇을 제안하겠습니까? – lracicot

+1

@lracicot 내 대답보기 편집;) – Gintro