Série : Symfony 7
Fichiers : https://github.com/NouvelleTechno/OpenBlog
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
etUserRepository
sont injectés directement dans la méthodeindex
. 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 dansUserRepository
(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.
- Titre: Affiché avec
- 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.