Chapitre 7.5 — EasyAdmin
Partie 7 : Twig & back-office — Chapitre 5/5 Version de référence : EasyAdmin 4 / Symfony 7.4.
⏱️ TL;DR
- EasyAdmin génère un back-office complet (CRUD, filtres, tri, recherche, formulaires, dashboard) en quelques minutes, à partir de vos entités.
- On configure en PHP (pas de génération de fichiers figés) : un Dashboard + un CrudController par entité, où l’on déclare les champs à afficher/éditer.
- Filtres, actions personnalisées, permissions par rôle, menu : tout se configure par méthodes (
configureFields,configureFilters,configureActions).- Immense valeur freelance : livrer un back-office admin fonctionnel très vite, puis personnaliser ce qui compte.
- Quand l’utiliser : admin CRUD standard. Quand faire à la main : UI très spécifique, écrans publics, workflows sur-mesure. On peut mélanger.
- Pour un dev Next.js : EasyAdmin ≈ React-Admin / Retool, mais rendu serveur et configuré en PHP à partir de vos entités Doctrine.
🎯 Objectifs
- Installer EasyAdmin et créer un dashboard.
- Générer un CRUD par entité et configurer ses champs.
- Ajouter filtres, actions et permissions.
- Choisir entre EasyAdmin et back-office à la main.
1. Installer et démarrer
composer require easycorp/easyadmin-bundle
php bin/console make:admin:dashboard # crée le DashboardControllerLe Dashboard est le point d’entrée de l’admin (route /admin) et déclare le menu.
// src/Controller/Admin/DashboardController.php
use App\Entity\{Booking, Provider, Service};
use EasyCorp\Bundle\EasyAdminBundle\Config\Dashboard;
use EasyCorp\Bundle\EasyAdminBundle\Config\MenuItem;
use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractDashboardController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;
class DashboardController extends AbstractDashboardController
{
#[Route('/admin', name: 'admin')]
public function index(): Response
{
return $this->render('admin/dashboard.html.twig');
}
public function configureDashboard(): Dashboard
{
return Dashboard::new()->setTitle('BookLab — Administration');
}
public function configureMenuItems(): iterable
{
yield MenuItem::linkToDashboard('Tableau de bord', 'fa fa-home');
yield MenuItem::linkToCrud('Prestataires', 'fa fa-store', Provider::class);
yield MenuItem::linkToCrud('Services', 'fa fa-list', Service::class);
yield MenuItem::linkToCrud('Réservations', 'fa fa-calendar', Booking::class);
}
}2. Un CrudController par entité
php bin/console make:admin:crud # choisir l'entité (ex. Service)// src/Controller/Admin/ServiceCrudController.php
use App\Entity\Service;
use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController;
use EasyCorp\Bundle\EasyAdminBundle\Field\{IdField, TextField, AssociationField};
class ServiceCrudController extends AbstractCrudController
{
public static function getEntityFqcn(): string
{
return Service::class;
}
public function configureFields(string $pageName): iterable
{
return [
IdField::new('id')->hideOnForm(),
TextField::new('name', 'Nom'),
AssociationField::new('provider', 'Prestataire'), // relation ManyToOne
];
}
}Et c’est tout : vous avez, pour Service, une liste paginée avec tri et recherche, un formulaire de création/édition (avec un sélecteur pour la relation provider), la suppression, le détail. Multipliez par entité pour couvrir tout l’admin.
3. Les types de champs
EasyAdmin fournit des champs qui s’adaptent au type de donnée : TextField, TextareaField, IntegerField, MoneyField, BooleanField, DateTimeField, ChoiceField (pour les enums), AssociationField (relations), ImageField, CollectionField… Chacun se configure (label, aide, options d’affichage, page où il apparaît).
use EasyCorp\Bundle\EasyAdminBundle\Field\{ChoiceField, DateTimeField, MoneyField};
ChoiceField::new('status')->setChoices(BookingStatus::cases())->renderAsBadges(),
DateTimeField::new('start', 'Début')->setFormat('dd/MM/yyyy HH:mm'),
MoneyField::new('amountCents', 'Montant')->setCurrency('EUR')->setStoredAsCents(),MoneyField::setStoredAsCents() gère le stockage en centimes (chapitre 6.1) et l’affichage en euros — exactement notre convention BookLab.
4. Filtres, actions, permissions
use EasyCorp\Bundle\EasyAdminBundle\Config\{Actions, Filters};
use EasyCorp\Bundle\EasyAdminBundle\Filter\{ChoiceFilter, EntityFilter};
public function configureFilters(Filters $filters): Filters
{
return $filters
->add(ChoiceFilter::new('status')->setChoices(/* ... */))
->add(EntityFilter::new('provider'));
}
public function configureActions(Actions $actions): Actions
{
return $actions
->add(Actions::INDEX, Actions::DETAIL) // ajoute un bouton "voir"
->setPermission(Actions::DELETE, 'ROLE_ADMIN'); // supprimer réservé aux admins
}On peut ajouter des actions personnalisées (ex. « Confirmer la réservation ») qui appellent un de vos services métier, et restreindre chaque action par rôle (intégration native avec la sécurité — Partie 10).
5. Sécuriser l’accès à l’admin
L’admin doit être protégé : on exige un rôle sur tout le préfixe /admin (config de sécurité, Partie 10) :
# config/packages/security.yaml (extrait)
access_control:
- { path: ^/admin, roles: ROLE_ADMIN }Ainsi, seuls les utilisateurs ROLE_ADMIN accèdent au back-office. EasyAdmin respecte en plus les permissions par action déclarées ci-dessus.
⚠️ Piège : oublier de protéger
/admin. EasyAdmin ne sécurise pas l’accès tout seul — c’est votre configuration de sécurité (access_control+ firewalls, Partie 10) qui décide qui entre. Un back-office non protégé, c’est la porte ouverte. Toujours verrouiller/adminpar rôle.
6. EasyAdmin vs à la main : la décision
Pour BookLab, on utilise EasyAdmin pour le back-office admin (gestion CRUD des prestataires, services, réservations) — c’est le meilleur rapport effort/résultat. Les écrans publics (consultés par les clients) et l’API (pour Next.js) sont, eux, faits sur-mesure.
💡 Pour un dev Next.js : EasyAdmin ≈ React-Admin ou Retool, mais généré depuis vos entités Doctrine et rendu serveur. Sur une mission freelance, livrer un back-office admin fonctionnel en une journée grâce à EasyAdmin (puis raffiner) est un argument commercial fort (Partie 17). Ne réinventez pas un CRUD admin à la main quand EasyAdmin le fait mieux et plus vite.
✏️ Exercices
Exercice 1. Ajoutez au menu du dashboard un lien vers le CRUD des Booking, avec une icône.
✅ Solution
Dans configureMenuItems() du DashboardController :
yield MenuItem::linkToCrud('Réservations', 'fa fa-calendar', Booking::class);(Nécessite un BookingCrudController généré via make:admin:crud.)
Exercice 2. Dans BookingCrudController, affichez le statut sous forme de badge et le montant en euros (stocké en centimes). Quels champs utilisez-vous ?
✅ Solution
ChoiceField::new('status')->setChoices(BookingStatus::cases())->renderAsBadges(),
MoneyField::new('amountCents', 'Montant')->setCurrency('EUR')->setStoredAsCents(),ChoiceField avec renderAsBadges() pour l’enum de statut ; MoneyField::setStoredAsCents() pour afficher en euros un montant stocké en centimes.
Exercice 3. Un client veut un back-office admin rapidement, mais aussi une page publique de réservation très soignée. Comment répartissez-vous EasyAdmin et le sur-mesure ?
✅ Solution
EasyAdmin pour le back-office admin (CRUD prestataires/services/réservations) — livré vite. À la main (Twig sur-mesure, ou front Next.js) pour la page publique de réservation qui exige une UX soignée et spécifique. On mélange : EasyAdmin pour l’interne, sur-mesure pour l’externe. (Et l’API pour Next.js viendra en Partie 11.)
🧠 Quiz de révision
1. Que génère EasyAdmin, et à partir de quoi ?
Un back-office complet (CRUD, filtres, tri, recherche, formulaires, dashboard) à partir de vos entités Doctrine, configuré en PHP.
2. Quels sont les deux types de contrôleurs EasyAdmin ?
Le Dashboard (point d’entrée /admin + menu) et un CrudController par entité (configureFields, filtres, actions).
3. Comment configure-t-on les champs affichés/éditables d’une entité ?
Via configureFields() du CrudController, qui retourne des champs typés (TextField, AssociationField, ChoiceField, MoneyField…).
4. EasyAdmin sécurise-t-il l’accès à l’admin tout seul ?
Non : c’est votre configuration de sécurité (access_control: ^/admin roles: ROLE_ADMIN, Partie 10) qui protège l’accès. EasyAdmin gère en plus les permissions par action.
5. Quand préférer le back-office à la main ?
Pour des UI très spécifiques, des workflows métier particuliers ou des écrans publics soignés. Pour du CRUD admin standard, EasyAdmin est plus rapide (et on peut mélanger).
Fin de la Partie 7. BookLab a un back-office : Twig, composants, AssetMapper, et un admin EasyAdmin fonctionnel. Le rendu full-stack est en place ; la Partie 8 va le rendre réactif sans SPA.
Prochaine étape : Partie 8 — Symfony UX : Stimulus, Turbo, LiveComponents — de la réactivité moderne sans quitter le serveur.