Qu'est-ce qu'un Criteria ?

Un Criteria est un builder de filtres pour les collections Doctrine. Il permet de filtrer une collection sans effectuer de requête SQL supplémentaire, avec une syntaxe expressive et fluide.

$criteria = Criteria::create()
->where(Criteria::expr()->eq('status', 'active'))
->orderBy(['createdAt' => 'DESC'])
->setMaxResults(10);

$results = $this->users->matching($criteria);

Pourquoi utiliser Criteria ?

Le cas d'usage principal des Criteria concerne les entités Doctrine, notamment dans les VirtualProperty ou getters personnalisés utilisés pour la sérialisation. Dans ces contextes, on ne peut pas injecter de repository, et les Criteria deviennent la solution idéale.

Exemple concret avec VirtualProperty

#[VirtualProperty(name: 'isAlreadySigned')]
#[Groups([EntityManager::GROUP_APPLICATION_LIST])]
public function
isAlreadySigned(): bool {
   $criteria = Criteria::create()
   ->where(Criteria::expr()->eq('status', Reply::STATUS_SIGNED))
   ->setMaxResults(1);

   return$this->version->getReplies()->matching($criteria)->count() > 0;
}

Dans cet exemple, la méthode est utilisée lors de la sérialisation de l'entité. Impossible d'injecter un repository ici, le Criteria est donc la seule option propre.

Criteria vs foreach/if

Avant les Criteria, on était souvent tentés d'utiliser des boucles foreach avec des conditions. Comparons les deux approches :

// ❌ Avec foreach/if
public functionhasSignedReply(): bool {
    foreach ($this->replies as$reply) {
        if ($reply->getStatus() === Reply::STATUS_ARCHIVED) {
             return true;
        }
    }
    return false;
}

// ✓ Avec Criteria
public functionhasSignedReply(): bool {
    $criteria = Criteria::create()
    ->where(Criteria::expr()->eq('status', Reply::STATUS_ARCHIVED))
    ->setMaxResults(1);
 
    return$this->replies->matching($criteria)->count() > 0;
}

Criteria vs Repository

Les Criteria ne remplacent pas les repositories. 

? Règle générale

Privilégiez les Repositories pour les requêtes complexes avec jointures.

Utilisez les Criteria dans les entités pour filtrer des collections en LazyLoad.

Bonnes pratiques

1. Créer des Criteria statiques réutilisables

Pour éviter la duplication de code, créez des méthodes statiques qui retournent des Criteria préconfigurés :

public static functioncreateActiveCriteria(): Criteria {
    returnCriteria::create() ->where(Criteria::expr()->eq('isActive', true));
}

// Utilisation
$active = $this->users->matching(User::createActiveCriteria());

2. Utiliser setMaxResults() pour optimiser

Lorsque vous cherchez à savoir si au moins un élément existe, limitez les résultats à 1 :

$criteria->setMaxResults(1); // Arrête la recherche au premier résultat

Conclusion

Les Criteria sont un outil puissant dans l'écosystème Doctrine, particulièrement utiles dans les contextes où les repositories ne sont pas accessibles. Ils offrent une syntaxe claire et expressive pour filtrer des collections, tout en étant plus performants et maintenables que des boucles foreach/if.

Retenez simplement : Repository pour les requêtes complexes, Criteria pour les filtrages dans les entités.