我有一个实体Offer
,与Country
实体之间存在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;
}
我想查询具有给定数组的国家/地区的所有商品。
更好理解的图片:
在这种情况下,它应该只显示Offer 1和Offer 2,因为前者有安道尔而后者有意大利。
从表格中我有一个国家实体的ArrayCollection。
是否可以在带有查询构建器的EntityRepository中执行此操作?
例如,这是我通过payoutMode过滤的方式,这是一个简单的int值:
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 :(得分:1)
在DQL中,您有IN
函数,它可以将右侧参数作为ID数组或实体数组。将其用于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'
语法在此上下文中是否有效。
但总的来说,就是这样。
答案 1 :(得分:0)
我想我找到了解决方案:
if(count($filter['countries'] ?? [])) {
$qb->leftJoin('offer.countries', 'countries')
->andWhere("countries IN (:ccs)")->setParameter(':ccs', $filter['countries']);
}