在Doctrine查询构建器中检查一个数组是否包含另一个数组的任何元素

7
我想知道在Doctrine查询构建器中是否可以检查一个数组是否包含另一个数组的任何元素。
在我的情况下,我想获取所有至少有一个类别与传递的参数数组匹配的产品(商品)。
Item和Category之间的关系如下:
/**
 *  @ORM\ManyToMany(targetEntity="Category")
 *  @ORM\JoinTable(name="items_categories",
 *      joinColumns={@ORM\JoinColumn(name="item_id", referencedColumnName="id", nullable=false)},
 *      inverseJoinColumns={@ORM\JoinColumn(name="category_id", referencedColumnName="id", nullable=false)}
 *      )
 */
private $categories;

我第一次尝试从项目库中获取数据(当我只需要检查一个值时,我知道这个方法是有效的):

public function getListItemsFromCatList($listCat) {
    $qb = $this->createQueryBuilder('i');

    $qb->select('i')
            ->where($qb->expr()->like('i.categories', ':listCat'))
            ->setParameter('listCat', '%"' . $listCat . '"%');

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

$listCat是一个类别实体数组:


array (size=5)
  0 => 
    object(ItemBundle\Entity\Category)[518]
      private 'id' => int 22
      private 'children' => 
        object(Doctrine\ORM\PersistentCollection)[520]
          private 'snapshot' => 
            array (size=2)
              ...
          private 'owner' => 
            &object(ItemBundle\Entity\Category)[518]
          private 'association' => 
            array (size=15)
              ...
          private 'em' => 
            object(Doctrine\ORM\EntityManager)[796]
              ...
          private 'backRefFieldName' => string 'parent' (length=6)
          private 'typeClass' => 
            object(Doctrine\ORM\Mapping\ClassMetadata)[579]
              ...
          private 'isDirty' => boolean false
          protected 'collection' => 
            object(Doctrine\Common\Collections\ArrayCollection)[515]
              ...
          protected 'initialized' => boolean true
      private 'parent' => null
      private 'name' => string 'Luxe' (length=4)
  1 => 
    object(ItemBundle\Entity\Category)[504]
      private 'id' => int 25
      private 'children' => 
        object(Doctrine\ORM\PersistentCollection)[505]
          private 'snapshot' => 
            array (size=0)
              ...
          private 'owner' => 
            &object(ItemBundle\Entity\Category)[504]
          private 'association' => 
            array (size=15)
              ...
          private 'em' => 
            object(Doctrine\ORM\EntityManager)[796]
              ...
          private 'backRefFieldName' => string 'parent' (length=6)
          private 'typeClass' => 
            object(Doctrine\ORM\Mapping\ClassMetadata)[579]
              ...
          private 'isDirty' => boolean false
          protected 'collection' => 
            object(Doctrine\Common\Collections\ArrayCollection)[500]
              ...
          protected 'initialized' => boolean false
      private 'parent' => 
        object(ItemBundle\Entity\Category)[512]
          private 'id' => int 23
          private 'children' => 
            object(Doctrine\ORM\PersistentCollection)[513]
              ...
          private 'parent' => 
            object(ItemBundle\Entity\Category)[518]
              ...
          private 'name' => string 'Bijoux' (length=6)
      private 'name' => string 'Bagues' (length=6)

请查看我的第二次编辑,我认为它可能有效。 - Alvin Bunk
2个回答

12

我会添加一个联接来解决它。

public function getListItemsFromCatList($listCat) {

    $em = $this->getDoctrine()->getManager();

    $qb = $em->createQueryBuilder();
    $qb->select('i')           
        ->from('AppBundle:Item', 'i')
        ->innerJoin('i.categories','cat')
        ->where('cat IN (:listCat)')
       ->setParameter('listCat', $listCat);

    return  = $qb->getQuery()->getResult();
}

请注意,这种方法将过滤掉项内的类别。这意味着当您尝试从给定项目 i 中获取类别 $i->getCategories() 时,它只会返回与 $listCat 匹配的类别。

如果您需要使用每个项中的所有类别,即使那些不与 $listCat 匹配。我建议您使用子查询进行过滤,并使用主查询返回完整的项目。如果您需要进一步帮助,请留言评论。


(Note: This is a translation. The original meaning and HTML tags have been preserved as requested.)

1
在我的情况下,只有与 $listCat 匹配的类别就可以了。因此,感谢您提供的答案。 - LedZelkin

1
尝试像这样使用您的查询构建器:

$em = $this->getDoctrine()->getManager();
$qb = $em->createQueryBuilder();
$qb->select('i')
    ->from('AppBundle:Item', 'i')
    ->where('i.categories LIKE :listCat')
    ->setParameter('listCat', '%"' . $listCat . '"%');

return  = $qb->getQuery()->getResult();

我认为应该可以工作。我假设你在使用Doctrine中的实体被称为Item

编辑#2-基于评论

您需要循环遍历数组并获取名称(我想),这是您要查找的类别。在此代码中,我显示了通过循环创建$cats变量,然后在IN查询中使用它。

foreach ($listCat as $item){
    $cats = $cats . "'" . $item.getName() . "'".',';
}
$cats = substr($cats, -1);


$em = $this->getDoctrine()->getManager();
$qb = $em->createQueryBuilder();
$qb->select('i')
    ->from('AppBundle:Item', 'i')
    ->where("i.categories IN (:listCat)")
    ->setParameter('listCat', $cats);

return  = $qb->getQuery()->getResult();

你能试试吗?我认为你需要类似的东西。


这和我的测试一样。$listcat是一个Category Entity数组。所以这行不通(我刚试了一下,结果出现以下错误:注意:数组转换为字符串)。 - LedZelkin
$listCat 是一个数组吗? - Alvin Bunk
请展示一下 $listCat 包含的内容。也许你可以使用 IN 替代? - Alvin Bunk
1
我遇到了这个错误:[语义错误]第0行,第47列附近的'categories IN':错误:无效的PathExpression。应该是StateFieldPathExpression或SingleValuedAssociationField。我认为这很正常,因为IN子句在左侧(i.categories)只等待一个值。 - LedZelkin
只要 $cats 包含正确的格式,它就应该可以工作。我编辑了字符串周围的单引号。此外,我看到你可以直接使用一个数组。我的答案应该是通用的。在发表进一步评论之前,请花时间进行故障排除。 - Alvin Bunk
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接