I am trying to set up a Criteria according to the Doctrine Docs.
Unfortunately they don't tell you how to access attributes of an related Object. Let me give you an example.
I have an ArrayCollection of Products. Every Product has a Category. I want to filter the ArrayCollection for a Category Name. Now I am trying to set up a Criteria as follows:
$criteria = Criteria::create()
->where(Criteria::expr()->eq("category.name", "SomeCategoryName"));
Now I get the following Exception:
An exception has been thrown during the rendering of a template ("Unrecognized field: category.name")
How can I access a related Object?
I looked into the source code Criteria::expr()->eq("name", --- second value ---)
. Second value expects an instance of Doctrine\Common\Collections\Expr\Value
. So it's not possible to put another Expr
or criteria
in there. Only the Expr
And
and Or
take another Expr
.
I'm pretty sure you are suppose to solve this with other functions like filter()
or get an iterator with getIterator()
. This is how it can be done with the filter()
method.
$filteredProducts =
$products->filter(function($key, $element) use ($categoryName) {
return $element->getCategory()->getName() === categoryName;
});
If you can an Iterator
for each next relation you can nest foreach loops and filter inside those.
That probably belongs in a repository method, rather than a filter method. If you're wanting to get a pre-filtered list of Products in a collection on a parent object (like an Order or something), you can filter the child collection in the query builder. However, you have to deal with the possibly confusing side-effect of not having fully hydrated objects.
This should give you a list of Order
objects, which only having Product
children matching a category name.
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);
}
}
If you don't know what kind of categories you're interested until later, then you're probably better using @Flip's solution anyway, and pre-hydrating all the categories. Using partial hydration and standard ArrayCollection::filter()
closures, performs pretty well in most cases.
That said, it would be quite nice as a feature. I suspect the Doctrine guys would be reluctant because the current Criteria
implementation is very light-weight and they probably want to keep it that way.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With