2017-06-07 1 views
0

Quelle est la bonne façon d'enchaîner des méthodes de référentiel personnalisées afin de créer une requête composée qui renvoie les entités en fonction de plusieurs conditions.Filtres de chaînage de référentiel personnalisé Doctrine?

Voici ce que je faisais:

use Doctrine\ORM\EntityRepository; 

class ingredientRepository extends EntityRepository 
{ 

    private $query; 

    public function initNewQuery() 
    { 
     $this->query = $this->createQueryBuilder('i')->join('i.product', 'p'); 
     return $this; 
    } 

    public function clearQuery() 
    { 
     $this->query = null; 
     return $this; 
    } 

    public function getResult(){ 
     $r = $this->query->getQuery()->getResult(); 
     $this->clearQuery(); 
     return $r; 
    } 

    public function filterByProductName($productName) 
    { 

     if(!$this->query) $this->initNewQuery(); 

     $this->query->andWhere('p.name LIKE :name')->setParameter('name', '%'.$productName.'%'); 

     return $this; 
    } 

    public function filterByMinContenu($contenu) 
    { 

     if(!$this->query) $this->initNewQuery(); 

     $this->query->andWhere('p.contenu > :contenu')->setParameter('contenu', $contenu); 

     return $this; 
    } 

    public function filterByType($type){ 

     if(!$this->query) $this->initNewQuery(); 

     $this->query->andWhere('i.type = :type')->setParameter('type', $type); 

     return $this; 

    }  

} 

Cela me permet de faire des choses comme:

$ingredients = $em->getRepository('ingredient')->initNewQuery()->filterByType(4)->getResult(); 

$ingredients = $em->getRepository('ingredient')->initNewQuery()->filterByProductName('ell')->filterByMinContenu(10)->getResult(); 

Ce qui est exactement ce que je veux! Mais ... je ne l'aime pas vraiment. Tout d'abord, ce n'est pas comment les méthodes par défaut comme findBy et ainsi de suite. Ceux-ci renvoient tous les résultats directement. Donc, cela ne semble pas juste de mélanger ces deux comportements. Ensuite, lorsque vous appelez uniquement la méthode filterByType, puis renvoyez les résultats, la requête utilisera une jointure dont elle n'a pas besoin. Je suppose que je pourrais trouver un moyen de faire la jointure seulement si j'en ai besoin, mais encore une fois, ne semble pas juste.

Toutes les idées sur la façon de le faire nettoyer un simple?

Répondre

0

réponse rapide sans test :)

use Doctrine\ORM\EntityRepository; 

class ingredientRepository extends EntityRepository 
{ 
    private $query; 

    private function initNewQuery() 
    { 
     $this->query = $this->createQueryBuilder('i'); 
    } 

    public function findBy($filterArray) 
    { 
     $this->initNewQuery(); 
     if (array_key_exists('productName', $filterArray)) { 
      $this->filterByProductName($filterArray['productName']); 
     } 
     if (array_key_exists('minContenu', $filterArray)) { 
      $this->filterByMinContenu($filterArray['minContenu']); 
     } 
     if (array_key_exists('type', $filterArray)) { 
      $this->filterByType($filterArray['type']); 
     } 
     return $this->query->getQuery()->getResult(); 
    } 

    private function filterByProductName($productName) 
    { 
     $this->query->join('i.product', 'p'); 
     $this->query->andWhere('p.name LIKE :name')->setParameter('name', '%'.$productName.'%'); 
    } 

    private function filterByMinContenu($contenu) 
    { 
     $this->query->andWhere('p.contenu > :contenu')->setParameter('contenu', $contenu); 
    } 

    private function filterByType($type) 
    { 
     $this->query->andWhere('i.type = :type')->setParameter('type', $type); 
    } 
} 

appel:

$ingredients = $em->getRepository('ingredient')->findBy(['type'=>4]); 

$ingredients = $em->getRepository('ingredient')->findBy(['productName'=>'ell', 'minContenu' => 10]); 
+0

Merci beaucoup pour cette réponse. Mais il n'y a toujours pas de solution pour la "jointure" inutile? Des idées là-dessus? – minychillo

+0

j'ai mis à jour la réponse. C'était une faute de frappe. :) Maintenant, il est joint seulement si le filtre de production existe. – mahkill