Doctrine EntityRepository,通过数组

时间:2017-01-13 16:33:28

标签: doctrine-orm symfony

我有一个实体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;
}

我想查询具有给定数组的国家/地区的所有商品。

更好理解的图片:

enter image description here

在这种情况下,它应该只显示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"
    }
  ]
}

2 个答案:

答案 0 :(得分:1)

在DQL中,您有IN函数,它可以将右侧参数作为ID数组或实体数组。将其用于JOIN条件

由于您已获得ArrayListCountry个实体,因此可能是这样的:

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