2012-09-10 9 views
5

Ho un filtro ascoltatore Doctrine2 & che funge da filtro per escludere qualsiasi entità non approvata/bozza, che funziona bene sull'entità a cui è applicata, tuttavia, non vedo come farlo funzionare per le sue relazioni .Come posso implementare un filtro Doctrine2 basato su una relazione?

Diciamo che l'entità si chiama Category, quindi ho prodotti relativi a tale categoria, quando faccio un findBy() per prodotti, ho bisogno della query per verificare che la categoria a cui si riferiscono sia approvata.

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

I bit in grassetto sono ciò che deve essere iniettata dal mio filtro o equivalente.

Come posso implementare questo?

Finora ho una sottointerrogazione iniettato come parte del dove nel filtro, ma questo sembra infernale, e sto pensando ci deve essere un modo migliore:

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

Quello che stai facendo sembra il migliore. Cosa faresti se la richiesta già contenga il JOIN? ecc ... – AdrienBrault

+0

@AdrienBrault bene al momento farebbe il join di nuovo e forse rompere, anche gli alias potrebbero teoricamente conflitto, sono sicuro che ci deve essere un modo migliore per farlo rispetto a quello che ho esemplificato, ma io non ho idea di come fare per farlo. – Steve

risposta

1

il meglio che posso pensare , è quello di recuperare i tuoi prodotti tramite l'oggetto categoria.
In questo modo è necessario filtrare solo per il campo category.approved.

Ad esempio:

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'; 
    } 
} 

Allora la vostra entità categoria dovrebbe avere una collezione di prodotti (ammesso che abbiate un rapporto bidirezionale).

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; 
    } 
} 

In questo modo è possibile innanzitutto recuperare la categoria

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

speranza che questo aiuti.

Edit:

Per rispondere alla domanda @lracicot e per dare un esempio per relazione unidirezionale: vorrei creare un metodo ProjectRepository ad esempio:

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

Ho un problema simile ma nel mio caso, la relazione da "Prodotto" a "Categoria" è (e deve essere) unidirezionale, quindi non posso ottenere i miei "Prodotti" dalla "Categoria". Cosa suggeriresti in quel caso? – lracicot

+1

@lracicot vedere la mia risposta modifica;) – Gintro

Problemi correlati