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 ofDoctrine\Common\Collections\Expr\Value
. So it's not possible to put anotherExpr
orcriteria
in there. Only theExpr
And
andOr
take anotherExpr
. I'm pretty sure you are suppose to solve this with other functions likefilter()
or get an iterator withgetIterator()
. This is how it can be done with thefilter()
method.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 havingProduct
children matching a category name.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.