2017-01-13 3 views
0

У меня есть объект, Offer с отношением ManyToMany к Country Entity (т.е. предложение может быть доступно на многих странах)Доктрина EntityRepository, запросить ManyToMany отношения массива

Class Offer 
{ 
    [...] 

    /** 
    * @ORM\ManyToMany(targetEntity="Country") 
    * @ORM\JoinTable(
    * name="offer_cc", 
    * joinColumns={ 
    *  @ORM\JoinColumn(name="offer_id", referencedColumnName="id") 
    * }, 
    * inverseJoinColumns={ 
    *  @ORM\JoinColumn(name="cc", referencedColumnName="cc") 
    * } 
    *) 
    */ 
    private $countries; 
} 

И я хочу запрос для всех предложений, которые имеют страну определенного массива.

Изображения лучше понять:

enter image description here

В этом случае он должен показывать только предложение 1 и предложение 2, поскольку первой Андорра и последние имеют Италию.

Из формы у меня есть ArrayCollection объектов страны.

Возможно ли это сделать в EntityRepository с построителем запросов?


Например, это, как я фильтровать payoutMode, который является простым ИНТ значение:

class OfferRepository extends EntityRepository 
{ 
    public function findAllFiltered(array $filter = []) 
    { 
     $qb = $this->createQueryBuilder('offer'); 

     // Show only active offers 
     $qb->where('offer.status=1'); 

     if($filter['payoutMode'] ?? null) { 
      $qb->andWhere("offer.payoutMode = :payoutMode")->setParameter(':payoutMode', $filter['payoutMode']); 
     } 

     // TODO add filter by cc, category, tags 

     return $qb->getQuery()->execute(); 
    } 
} 

Здесь $filter['countries'] содержит:

ArrayCollection {#748 ▼ 
    -elements: array:2 [▼ 
    0 => Country {#762 ▼ 
     -cc: "AD" 
    } 
    1 => Country {#769 ▼ 
     -cc: "IT" 
    } 
    ] 
} 
+0

Нам нужен код, который обрабатывает форму фильтра, и тот, который делает запрос на основе этих фильтров. –

+0

Я добавил код репозитория –

ответ

0

Я думаю, я нашел решение :

if(count($filter['countries'] ?? [])) { 
    $qb->leftJoin('offer.countries', 'countries') 
     ->andWhere("countries IN (:ccs)")->setParameter(':ccs', $filter['countries']); 
} 
1

В DQ L есть функция IN, которая может принимать в качестве аргумента правой руки массив идентификаторов или массив сущностей. Используйте его для JOIN состояния

Поскольку вы уже получаете ArrayList из Country сущности, это может быть что-то вроде этого:

class OfferRepository extends EntityRepository 
{ 
    public function findAllFiltered(array $filter = []) 
    { 
     $qb = $this->createQueryBuilder('offer'); 

     // Show only active offers 
     $qb->where('offer.status=1'); 

     if($filter['payoutMode'] ?? null) { 
      $qb->join("offer.payoutMode = :payoutMode")->setParameter(':payoutMode', $filter['countries']); 
     } 

     if(!empty($filter['payoutMode'])) { 
      $qb->join('offer.countries', 'c', Expr\Join::WITH, 'c IN :countries') 
       ->setParameter(':countries', $filter['countries']); 
     } 
     // TODO add filter by cc, category, tags 

     return $qb->getQuery()->execute(); 
    } 
} 

код не проверял, так что я мог испортить что-то с синтаксисом DQL JOIN. Я не уверен, что синтаксис 'c IN :countries' действителен в этом контексте. Но в общем, так оно и есть.