12

我正在尝试根据Doctrine Docs设置标准。

不幸的是,他们没有告诉您如何访问相关对象的属性。让我给你举个例子。

我有一个产品的 ArrayCollection。每个产品都有一个类别。我想过滤类别名称的 ArrayCollection。现在我正在尝试设置如下标准:

$criteria = Criteria::create()
  ->where(Criteria::expr()->eq("category.name", "SomeCategoryName"));

现在我得到以下异常:

An exception has been thrown during the rendering of a template ("Unrecognized field: category.name")

如何访问相关的对象?

4

2 回答 2

12

我查看了源代码Criteria::expr()->eq("name", --- second value ---)。第二个值需要一个 的实例Doctrine\Common\Collections\Expr\Value。所以不可能再放一个Exprcriteria放在那里。只有Expr AndOr采取另一个Expr。我很确定你想用其他函数来解决这个问题,filter()或者用getIterator(). 这就是如何使用该filter()方法完成的。

$filteredProducts = 
    $products->filter(function($key, $element) use ($categoryName) {
        return $element->getCategory()->getName() === categoryName;
    });

如果您可以Iterator为每个下一个关系创建一个,您可以嵌套 foreach 循环并在其中进行过滤。

于 2013-08-10T08:56:42.153 回答
4

这可能属于存储库方法,而不是过滤器方法。如果您想在父对象(如订单或其他东西)的集合中获取预先过滤的产品列表,您可以在查询构建器中过滤子集合。但是,您必须处理没有完全水合的物体可能令人困惑的副作用。

这应该为您提供一个Order对象列表,其中只有Product与类别名称匹配的子项。

class OrderRepository extends EntityRepository {
  public function findOrderWithProductCategory($category)
  {
    $builder = $this->createQueryBuilder('o')
      ->select('o, p')
      ->leftJoin('o.products', 'p')
      ->join('p.category', 'c', 'WITH', 'c.name = :category')
      ->setParameter('category', $category);
  }
}

如果您直到稍后才知道自己感兴趣的类别,那么您可能最好还是使用@Flip 的解决方案,并预先对所有类别进行补水。在大多数情况下,使用部分水合作用和标准ArrayCollection::filter()封闭,表现相当不错。

也就是说,它作为一个功能会非常好。我怀疑 Doctrine 的人会不情愿,因为当前的Criteria实现非常轻量级,他们可能希望保持这种方式。

于 2015-04-09T01:42:23.147 回答