Reputation: 1549
I'm looking to a better way to write this function. It's inside a Doctrine Entity Model
public function getCompanySubscriptions()
{
foreach ($this->subscriptions as $key => $value) {
if ($value->getPlan()->getType() == 'E' && $value->getActive()) {
return $value;
}
}
return null;
}
$this->subscriptions
is a many-to-one collection and can have different "types" (but only one of them with type "E").
Problem is: If the Company
has too many $subscriptions
this function will be too slow to return that only one of type "E" which I need to check when building the view with TWIG. The solution would be to use a QueryBuilder
, but I haven't found a way to use it directly from the entity model.
Upvotes: 0
Views: 2356
Reputation: 44422
You cannot use a QueryBuilder
inside your entity, but instead you can use doctrine Criteria
for filtering collections (on SQL level). Check the documentation chapter 8.8. Filtering Collections for more details on Criteria
.
If the collection has not been loaded from the database yet, the filtering API can work on the SQL level to make optimized access to large collections.
For example to only get active subscriptions:
$subscriptions = $this->getCompanySubscriptions();
$criteria = Criteria::create()
->where(Criteria::expr()->eq("active", true));
$subscriptions = $subscriptions ->matching($criteria);
Like that you can solve your performance issues, since the collection is loaded from the database using the conditions from the Criteria
directly.
The problem in your case might be that you need to join on Plan
, but joining is not possible in a Criteria
. So if joining is really necessary then you should consider using a custom query where you do the join with conditions in your company EntityRepository
(for example with a QueryBuilder
).
Note.
The foreach
in your question can be rewritten using the filter
method from the ArrayCollection
class. The filter takes a predicate and all elements satisfying the predicate will be returned.
Look also here in the doctrine 2 class documentation for more info.
Your predicate would look something like:
$predicate = function($subscription){
$subscription->getPlan()->getType() == 'E' && $subscription->getActive();
}
and then:
return $this->subscriptions->filter($predicate);
Upvotes: 1