简体   繁体   中英

Query Builder inside entity - Doctrine

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.

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);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM