Doctrine fournit des outils performants et flexibles pour gérer les entités et interagir avec la base de données. Cette section explore comment récupérer, manipuler, et optimiser les requêtes pour les entités grâce aux repositories, au DQL (Doctrine Query Language), et au QueryBuilder.
Le Repository : Centralisateur de Requêtes
a. Rôle du Repository
Un repository centralise toutes les requêtes liées à une entité spécifique. Bien que majoritairement utilisé pour des opérations de lecture (SELECT), il peut également contenir des méthodes pour insérer, modifier, ou supprimer des données.
Chaque entité dispose de son propre repository. Si aucun repository personnalisé n’est défini, Doctrine utilise une classe par défaut. Pour accéder au repository d’une entité, vous pouvez utiliser l’EntityManager et sa méthode getRepository()
.
$repository = $this->em->getRepository(App\Entity\Livre::class);
$livre = $repository->find(1);
Dans cet exemple :
getRepository()
récupère le repository lié à l’entité Livre.find()
retourne l’entité dont la clé primaire vaut1
.
b. Méthodes de Base
Doctrine fournit des méthodes intégrées pour effectuer des requêtes courantes :
find($id)
- Récupère une entité par sa clé primaire.
- Exemple :
$livre = $repository->find(15);
findAll()
- Retourne toutes les entités persistées en base sous forme de tableau.
findOneBy(array $criteria)
- Recherche une entité correspondant aux critères spécifiés.
- Exemple :
$livre = $repository->findOneBy(['titre' => '1984']);
findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
- Recherche plusieurs entités selon des critères, avec des options de tri et de pagination.
- Exemple :
$livres = $repository->findBy( ['auteur' => 'George Orwell'], ['dateParution' => 'DESC'], 10, 0 );
c. Repositories Personnalisés
Pour des besoins spécifiques, il est possible de créer des repositories personnalisés en étendant EntityRepository
:
- Définir le Repository
namespace App\Repository; use Doctrine\ORM\EntityRepository; class LivreRepository extends EntityRepository { public function rechercherParAuteur($auteur) { return $this->createQueryBuilder('l') ->andWhere('l.auteur = :auteur') ->setParameter('auteur', $auteur) ->getQuery() ->getResult(); } }
- Associer le Repository à l’Entité
#[ORM\Entity(repositoryClass: LivreRepository::class)] class Livre { // ... }
Le DQL : Doctrine Query Language
Le DQL est un langage de requête inspiré du SQL mais conçu pour interagir avec les entités et leurs relations. Doctrine traduit automatiquement ces requêtes DQL en SQL pour la base de données.
a. Syntaxe de Base
- SELECT : Permet de récupérer des entités.
- FROM : Définit l’entité principale.
- WHERE : Applique des filtres.
- JOIN : Réalise des jointures.
Exemple simple :
$query = $this->em->createQuery('SELECT l FROM App\Entity\Livre l WHERE l.titre = :titre');
$query->setParameter('titre', '1984');
$livre = $query->getOneOrNullResult();
b. Jointures
Les jointures permettent de récupérer des entités liées sans écrire plusieurs requêtes.
$query = $this->em->createQuery(
'SELECT l, a FROM App\Entity\Livre l JOIN l.auteur a WHERE a.nom = :nom'
);
$query->setParameter('nom', 'Orwell');
$livres = $query->getResult();
JOIN
: Jointure obligatoire.LEFT JOIN
: Jointure optionnelle.
c. Paramètres
Les paramètres rendent les requêtes dynamiques et sécurisées. Vous pouvez utiliser :
- Paramètres nominatifs (
:nom
) :$query->setParameter('nom', 'Orwell');
- Paramètres numérotés (
?1
) :$query->setParameter(1, 'Orwell');
Le QueryBuilder
Le QueryBuilder est un outil puissant et lisible pour construire dynamiquement des requêtes DQL. Il évite les erreurs liées à la concaténation manuelle des chaînes de requêtes.
a. Exemple Basique
$qb = $this->em->createQueryBuilder();
$qb->select('l')
->from('App\Entity\Livre', 'l')
->where('l.auteur = :auteur')
->setParameter('auteur', 'Orwell');
b. Requête Dynamique
Ajoutez des conditions de manière conditionnelle :
$qb = $this->em->createQueryBuilder('l');
if ($pseudo) {
$qb->andWhere('l.pseudo LIKE :pseudo')
->setParameter('pseudo', '%'.$pseudo.'%');
}
return $qb->getQuery()->getResult();
c. Documentation
Consultez la documentation officielle pour plus d’informations : QueryBuilder – Doctrine
Pagination avec Doctrine
Doctrine ne propose pas de LIMIT directement en DQL. Cependant, l’objet Query offre des méthodes pratiques :
setMaxResults()
: Limite le nombre de résultats.setFirstResult()
: Définit un décalage pour la pagination.
Exemple :
$query = $this->em->createQuery('SELECT l FROM App\Entity\Livre l ORDER BY l.id');
$query->setFirstResult(($page - 1) * $nbParPage)
->setMaxResults($nbParPage);
Recommandations
- Évitez les Requêtes Non Optimisées :
- Les jointures implicites (lazy loading) peuvent générer un grand nombre de requêtes SQL.
- Utilisez des jointures explicites avec JOIN pour limiter les appels.
- Cachez les Résultats des Requêtes :
- Doctrine permet de mettre en cache les résultats pour améliorer les performances des applications lourdes.
- Utilisez les Outils de Debug Symfony :
- Le profiler Symfony affiche le nombre de requêtes SQL exécutées.
- Référez-vous à la Documentation Officielle :
Les repositories, le DQL et le QueryBuilder offrent une grande souplesse pour interagir avec vos entités et optimiser vos requêtes. En combinant ces outils avec des bonnes pratiques comme le cache et les jointures explicites, vous pouvez gérer efficacement les données dans une application Symfony robuste et évolutive.