13 - Accès aux données relationnelles (Symfony 7)

Temps de lecture : 19 minutes environ.

Dans ce 13e tutoriel de la série Symfony 7 sur le projet Open Blog, nous allons explorer comment récupérer des données relationnelles dans une base de données en utilisant Doctrine, puis les afficher dans une page web. Nous verrons notamment comment récupérer les articles, leurs catégories, et les auteurs les plus actifs.

Mise à jour du contrôleur principal

Le contrôleur est responsable de traiter les requêtes HTTP et de renvoyer une réponse appropriée. Dans notre cas, il va récupérer les données depuis la base de données et les passer au template Twig pour être affichées.

<?php

namespace App\Controller;

use App\Repository\PostsRepository;
use App\Repository\UsersRepository;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;

class MainController extends AbstractController
{
#[Route('/', name: 'app_main')]
public function index(PostsRepository $postsRepository, UsersRepository $usersRepository): Response
{
$lastPost = $postsRepository->findOneBy([], ['id' => 'desc']);
$posts = $postsRepository->findBy([], ['id' => 'desc'], 8);

$authors = $usersRepository->getUsersByPosts(4);

return $this->render('main/index.html.twig', compact('lastPost','posts', 'authors'));
}

#[Route('/mentions-legales', name: 'app_mentions')]
public function mentions(): Response
{
return $this->render('main/mentions.html.twig');
}
}
  • Injection de dépendances: PostRepository et UserRepository sont injectés directement dans la méthode index. Symfony gère cela automatiquement pour nous.
  • Récupération des articles:
    • findOneBy: Utilisée pour récupérer le dernier article publié en triant par l'ID décroissant (DESC).
    • findBy: Utilisée pour récupérer les 7 articles les plus récents. On passe un tableau vide pour les critères ([]), on spécifie l'ordre par ID décroissant, et on limite à 7 résultats.
  • Récupération des auteurs les plus actifs: La méthode getUsersByPostCount est définie dans UserRepository (nous la verrons en détail plus loin) et retourne les 4 auteurs ayant le plus grand nombre de publications.
  • Passage des données au template Twig: Les données sont passées à Twig via la méthode render. compact crée un tableau associatif où les clés sont les noms des variables et les valeurs leurs contenus respectifs.

Méthodes Standards dans PostRepository

Doctrine nous offre des méthodes prêtes à l'emploi pour effectuer des opérations courantes sur les entités. Voici une description des méthodes utilisées :

  • findOneBy: Retourne un seul objet correspondant aux critères spécifiés. Nous l'avons utilisé pour récupérer le dernier article.
  • findBy: Retourne un tableau d'objets correspondant aux critères spécifiés. Elle accepte des paramètres pour les critères, l'ordre, la limite, et le décalage (offset).

Création d'une Méthode Personnalisée dans UserRepository

Pour récupérer les auteurs les plus actifs, nous devons écrire une méthode personnalisée dans UserRepository. Cette méthode comptera le nombre de posts de chaque utilisateur et les triera en fonction de ce nombre.

   /**
* @return Users[] Returns an array of Users objects
*/
public function getUsersByPosts($limit): array
{
return $this->createQueryBuilder('u')
->addSelect('COUNT(p) as total')
->leftJoin('u.posts', 'p')
->groupBy('u.id')
->orderBy('total', 'desc')
->setMaxResults($limit)
->getQuery()
->getResult()
;
}
  • QueryBuilder: Symfony fournit un QueryBuilder qui permet de construire des requêtes SQL en utilisant une syntaxe orientée objet.
  • createQueryBuilder('u'): Crée un constructeur de requêtes où u est un alias pour l'entité User.
  • addSelect('COUNT(p) AS total'): compte le nombre de posts associés à chaque utilisateur.
  • leftJoin('u.posts', 'p'): Effectue une jointure entre les utilisateurs et leurs posts. La jointure à gauche (leftJoin) garantit que tous les utilisateurs sont inclus même s'ils n'ont pas de posts.
  • groupBy('u.id'): Groupe les résultats par utilisateur.
  • orderBy('total', 'DESC'): Trie les utilisateurs par le nombre total de posts, en ordre décroissant.
  • setMaxResults($limit): Limite les résultats au nombre spécifié.

5. Mise à jour du Template Twig (index.html.twig)

Nous devons maintenant mettre à jour le fichier de template Twig pour afficher les données récupérées.

{% extends 'base.html.twig' %}

{% block title %}Accueil{% endblock %}

{% block body %}
<header>
<div>
<img src="{{ asset('uploads/articles/') ~ lastPost.featuredImage }}" alt="{{ lastPost.title }}">
</div>
<div>
{% for category in lastPost.categories %}
<span>{{ category.name }}</span>
{% endfor %}
</div>
<h3>{{ lastPost.title }}</h3>
<div>{{ lastPost.content }}</div>
<p>{{ lastPost.users.nickname }}</p>
</header>
<main>
<section>
<h2>Derniers articles</h2>
{% for post in posts %}
<div>
<img src="{{ asset('uploads/articles/mini/300x300-') ~ post.featuredImage }}" alt="{{ post.title }}">
</div>
<div>
{% for category in post.categories %}
<span>{{ category.name }}</span>
{% endfor %}
</div>
<h3>{{ post.title }}</h3>
<p>{{ post.users.nickname }}</p>
{% endfor %}
</section>
<section>
<h2>Auteurs actifs</h2>
{% for author in authors %}
<h3>{{ author[0].nickname }} {{author.total}}</h3>
{% endfor %}
</section>
</main>
{% endblock %}
  • Affichage du dernier article:
    • Titre: Affiché avec {{ lastPost.title }}.
    • Image: Utilise la fonction asset pour générer le chemin vers l'image. Le nom de l'image est concaténé avec le chemin d'accès.
    • Catégories: Utilisation de la boucle for pour afficher toutes les catégories associées à l'article.
    • Contenu: Affiche un extrait (les 200 premiers caractères) du contenu de l'article.
    • Auteur: Affiche le pseudonyme de l'auteur.
  • Affichage des derniers articles: Structure similaire à celle du dernier article, mais affichant plusieurs articles.
  • Affichage des auteurs actifs: Une boucle for affiche les auteurs et le nombre d'articles qu'ils ont publiés.

Optimisation des Requêtes

Chaque relation (comme post.categories ou post.user) déclenche une requête supplémentaire. Cette approche n'est pas toujours optimale, car elle peut conduire à un grand nombre de requêtes SQL, surtout si vous avez beaucoup de relations à charger.

Pour optimiser, vous pouvez utiliser le mécanisme de Jointure Eager dans Doctrine. Cela permet de charger toutes les relations nécessaires en une seule requête SQL.

Conclusion

Dans ce tutoriel, nous avons vu comment :

  • Récupérer des données relationnelles complexes en utilisant Doctrine.
  • Afficher ces données dans un template Twig.
  • Écrire des méthodes personnalisées dans un repository pour des besoins spécifiques.
  • Optimiser les requêtes pour améliorer les performances.

Ces techniques vous permettent de construire des pages dynamiques et performantes tout en maintenant un code propre et maintenable.

Obtenir de l'aide

Pour obtenir de l'aide, vous pouvez accéder au serveur Discord pour une entraide par chat.

13 - Accès aux données relationnelles (Symfony 7)
Article publié le

Catégories : Symfony Symfony 7

Mots-clés : Base de données Symfony donnees relations Symfony 7

Partager : Partager sur Facebook Partager sur Twitter Partager sur LinkedIn