Using Collection Filtering with Doctrine Criteria

Using Collection Filtering with Doctrine Criteria

Table of Contents

Introduction

When working with Doctrine entities and collections in Symfony, you often need to filter related entities based on specific conditions. In this article, I'll show how to use Doctrine's Criteria object to filter collections and optimize your queries.

Basic Collection Retrieval

Suppose you have an entity with a collection of related entities, like a Publisher with many Articles. You might have a method like this to retrieve all related entities:

public function getArticles(): Collection
{
    return $this->articles;
}

This method returns all articles associated with the publisher. However, what if you want to filter these articles based on certain conditions?

Using Criteria for Filtering

Doctrine's Criteria object allows you to filter collections properly. Here's an example of how to use Criteria to retrieve only published articles:

use Doctrine\Common\Collections\Criteria;

public function getPublishedArticles(): Collection
{
    $criteria = Criteria::create()
        ->andWhere(Criteria::expr()->eq('published', true));
    return $this->articles->matching($criteria);
}

This method creates a Criteria object that filters the articles based on the 'published' field being true. The matching() method applies this criteria to the collection, returning only the published articles.

Optimization: Counting Without Loading

Sometimes, you might need to know the count of related entities without actually loading them all. This is where the EXTRA_LAZY fetch mode comes in handy.

First, modify your entity property annotation to use EXTRA_LAZY:

/**
 * @ORM\OneToMany(targetEntity=Article::class, mappedBy="category", fetch="EXTRA_LAZY")
 */
private $articles;

Now, when you want to get the count of articles in a Twig template, you can simply use:

{{ publisher.getPublishedArticles|length }}

This will execute an optimized COUNT query instead of loading all the articles.

Conclusion

Using Doctrine's Criteria object and EXTRA_LAZY fetch mode can greatly improve the optimize of your Symfony applications when working with collections. By filtering at the collection level and optimizing count queries, you can reduce database load and improve response times.