学说 2.3 标准。访问相关对象

问题描述 投票:0回答:3

我正在尝试根据 The Doctrine Docs 建立一个标准。

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

我有一个产品数组。每个产品都有一个类别。我想过滤 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")

如何访问相关对象?

symfony doctrine-orm criteria
3个回答
13
投票

我查看了源代码

Criteria::expr()->eq("name", --- second value ---)
。第二个值需要一个
Doctrine\Common\Collections\Expr\Value
的实例。所以不可能再放一个
Expr
criteria
在那里。只有
Expr
And
Or
需要另一个
Expr
。 我很确定您应该使用
filter()
等其他函数来解决这个问题,或者使用
getIterator()
获取迭代器。这就是使用
filter()
方法来完成的方法。

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

如果您可以为每个下一个关系添加

Iterator
,您可以嵌套 foreach 循环并在其中进行过滤。


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
实现非常轻量级,他们可能想保持这种状态。


0
投票

如本评论中所述 https://github.com/doctrine/orm/issues/2918#issuecomment-2008389326 匹配嵌套属性的条件已经在 ArrayCollections 上工作,但不适用于 PersistentCollections(尚未)(如此处所述 https ://stackoverflow.com/a/44099807/8721626持久集合是惰性的)。

您可能希望在多个位置使用标准,而不是使用存储库方法或 array_filters,因此解决方法(具有内存权衡)是预先加载“类别”(在 op 情况下),例如:

$criteria = Criteria::create()
  ->where(Criteria::expr()->eq("category.name", "SomeCategoryName"));
foreach ($this->getCategories() as $category) {
   // do  nothing but loading categories
}
return $this->categories->matching($criteria); // $this->categories is now an ArrayCollection
© www.soinside.com 2019 - 2024. All rights reserved.