Symfony11 min

EasyAdmin : un back-office Symfony en 1h

Par Pierre-Arthur Demengel
SymfonyEasyAdminAdministrationCRUD

Chaque application metier a besoin d'un back-office. Le construire from scratch prend des semaines. EasyAdmin 4 permet de creer un panneau d'administration complet et fonctionnel en une heure - avec CRUD, filtres, actions personnalisees et controle d'acces. Voici comment, etape par etape.

Installation

EasyAdmin s'installe en une commande :

composer require easycorp/easyadmin-bundle

Le bundle se configure automatiquement via Symfony Flex. Aucun fichier YAML a editer manuellement.

Le DashboardController

Le point d'entree d'EasyAdmin est le DashboardController. Il definit le menu de navigation, le titre et les permissions globales :

// src/Controller/Admin/DashboardController.php
namespace App\Controller\Admin;

use App\Entity\Article;
use App\Entity\Category;
use App\Entity\User;
use App\Entity\Order;
use EasyAdmin\Config\Dashboard;
use EasyAdmin\Config\MenuItem;
use EasyAdmin\Controller\AbstractDashboardController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Security\Http\Attribute\IsGranted;

class DashboardController extends AbstractDashboardController
{
    #[Route('/admin', name: 'admin')]
    #[IsGranted('ROLE_ADMIN')]
    public function index(): Response
    {
        return $this->render('admin/dashboard.html.twig');
    }

    public function configureDashboard(): Dashboard
    {
        return Dashboard::new()
            ->setTitle('Mon Application')
            ->setFaviconPath('favicon.ico')
            ->setLocales(['fr', 'en']);
    }

    public function configureMenuItems(): iterable
    {
        yield MenuItem::linkToDashboard('Tableau de bord', 'fa fa-home');

        yield MenuItem::section('Contenu');
        yield MenuItem::linkToCrud('Articles', 'fa fa-newspaper', Article::class);
        yield MenuItem::linkToCrud('Categories', 'fa fa-tags', Category::class);

        yield MenuItem::section('Commerce');
        yield MenuItem::linkToCrud('Commandes', 'fa fa-shopping-cart', Order::class);

        yield MenuItem::section('Utilisateurs');
        yield MenuItem::linkToCrud('Utilisateurs', 'fa fa-users', User::class);

        yield MenuItem::section('Liens');
        yield MenuItem::linkToUrl('Site public', 'fa fa-globe', '/');
    }
}

L'attribut #[IsGranted('ROLE_ADMIN')] securise l'ensemble du dashboard. Seuls les utilisateurs avec le role ROLE_ADMIN y accedent. Pour approfondir la gestion des roles, consultez l'article sur la securite Symfony.

CrudController : gerer une entite

Chaque entite administree possede son CrudController. Voici un exemple complet pour une entite Article :

// src/Controller/Admin/ArticleCrudController.php
namespace App\Controller\Admin;

use App\Entity\Article;
use EasyAdmin\Config\Action;
use EasyAdmin\Config\Actions;
use EasyAdmin\Config\Crud;
use EasyAdmin\Config\Filters;
use EasyAdmin\Controller\AbstractCrudController;
use EasyAdmin\Field\AssociationField;
use EasyAdmin\Field\BooleanField;
use EasyAdmin\Field\DateTimeField;
use EasyAdmin\Field\IdField;
use EasyAdmin\Field\ImageField;
use EasyAdmin\Field\SlugField;
use EasyAdmin\Field\TextareaField;
use EasyAdmin\Field\TextEditorField;
use EasyAdmin\Field\TextField;

class ArticleCrudController extends AbstractCrudController
{
    public static function getEntityFqcn(): string
    {
        return Article::class;
    }

    public function configureCrud(Crud $crud): Crud
    {
        return $crud
            ->setEntityLabelInSingular('Article')
            ->setEntityLabelInPlural('Articles')
            ->setDefaultSort(['publishedAt' => 'DESC'])
            ->setSearchFields(['title', 'content', 'author.name'])
            ->setPaginatorPageSize(30);
    }

    public function configureFields(string $pageName): iterable
    {
        yield IdField::new('id')->hideOnForm();

        yield TextField::new('title', 'Titre')
            ->setRequired(true)
            ->setMaxLength(255);

        yield SlugField::new('slug')
            ->setTargetFieldName('title')
            ->hideOnIndex();

        yield TextEditorField::new('content', 'Contenu')
            ->hideOnIndex();

        yield ImageField::new('coverImage', 'Image')
            ->setBasePath('/uploads/articles')
            ->setUploadDir('public/uploads/articles')
            ->setRequired(false);

        yield AssociationField::new('category', 'Categorie')
            ->autocomplete();

        yield AssociationField::new('author', 'Auteur')
            ->setCrudController(UserCrudController::class);

        yield BooleanField::new('isPublished', 'Publie');

        yield DateTimeField::new('publishedAt', 'Date de publication')
            ->setFormat('dd/MM/yyyy HH:mm');

        yield DateTimeField::new('createdAt', 'Cree le')
            ->hideOnForm();
    }

    public function configureFilters(Filters $filters): Filters
    {
        return $filters
            ->add('category')
            ->add('author')
            ->add('isPublished')
            ->add('publishedAt');
    }

    public function configureActions(Actions $actions): Actions
    {
        $publishAction = Action::new('publish', 'Publier')
            ->linkToCrudAction('publishArticle')
            ->setCssClass('btn btn-success')
            ->displayIf(fn (Article $article) => !$article->isPublished());

        return $actions
            ->add(Crud::PAGE_INDEX, $publishAction)
            ->add(Crud::PAGE_DETAIL, $publishAction)
            ->setPermission(Action::DELETE, 'ROLE_SUPER_ADMIN');
    }

    public function publishArticle(): Response
    {
        // Logique de publication...
    }
}

Ce controller definit tout ce dont vous avez besoin : les champs affiches sur chaque page (listing, formulaire, detail), les filtres de recherche, le tri par defaut et les actions personnalisees.

Types de champs disponibles

EasyAdmin fournit une trentaine de types de champs prets a l'emploi :

  • Texte - TextField, TextareaField, TextEditorField (WYSIWYG), SlugField
  • Nombres - IntegerField, NumberField, MoneyField, PercentField
  • Choix - BooleanField, ChoiceField, CountryField, LanguageField
  • Dates - DateField, DateTimeField, TimeField
  • Medias - ImageField, FileField
  • Relations - AssociationField (gere ManyToOne, OneToMany, ManyToMany)
  • Special - CodeEditorField, ColorField, EmailField, UrlField

Chaque champ se configure avec une API fluide. Pour les formulaires complexes qui depassent les capacites d'EasyAdmin, vous pouvez integrer des FormTypes Symfony classiques - consultez le guide ultime des FormTypes pour les techniques avancees.

Actions personnalisees

Au-dela des actions CRUD standard, EasyAdmin permet de creer des actions metier. Par exemple, exporter les donnees en CSV :

public function configureActions(Actions $actions): Actions
{
    $exportAction = Action::new('export', 'Exporter CSV')
        ->linkToUrl(function () {
            return $this->container->get('router')->generate('admin_export_articles');
        })
        ->setCssClass('btn btn-outline-primary')
        ->setIcon('fa fa-download')
        ->createAsGlobalAction();

    return $actions
        ->add(Crud::PAGE_INDEX, $exportAction);
}

Les actions globales apparaissent en haut de la page de listing. Les actions par entite apparaissent sur chaque ligne. Vous pouvez conditionner leur affichage avec displayIf() et leur acces avec setPermission().

Actions par lot (batch)

EasyAdmin supporte les actions sur une selection d'entites. Les utilisateurs cochent les lignes souhaitees, puis executent l'action :

$batchPublish = Action::new('batchPublish', 'Publier la selection')
    ->linkToCrudAction('batchPublish')
    ->addCssClass('btn btn-success');

return $actions->addBatchAction($batchPublish);

Controle d'acces granulaire

La securite d'EasyAdmin s'appuie sur le systeme de securite de Symfony. Vous pouvez definir des permissions a chaque niveau :

public function configureActions(Actions $actions): Actions
{
    return $actions
        // Seuls les ROLE_EDITOR peuvent creer
        ->setPermission(Action::NEW, 'ROLE_EDITOR')
        // Seuls les ROLE_ADMIN peuvent supprimer
        ->setPermission(Action::DELETE, 'ROLE_ADMIN')
        // Tout le monde peut lire (dans le cadre du firewall admin)
        ->setPermission(Action::INDEX, 'ROLE_USER');
}

Vous pouvez aussi filtrer les entites affichees selon l'utilisateur connecte en surchargeant createIndexQueryBuilder() :

public function createIndexQueryBuilder(
    SearchDto $searchDto,
    EntityDto $entityDto,
    FieldCollection $fields,
    FilterCollection $filters,
): QueryBuilder {
    $qb = parent::createIndexQueryBuilder(
        $searchDto, $entityDto, $fields, $filters
    );

    // Les editeurs ne voient que leurs propres articles
    if (!$this->isGranted('ROLE_ADMIN')) {
        $qb->andWhere('entity.author = :user')
           ->setParameter('user', $this->getUser());
    }

    return $qb;
}

Personnalisation des templates

EasyAdmin permet de surcharger chaque template Twig. Creez un fichier dans templates/bundles/EasyAdminBundle/ et EasyAdmin l'utilisera automatiquement. Pour le dashboard, un template personnalise avec des statistiques :

{# templates/admin/dashboard.html.twig #}
{% extends '@EasyAdmin/page/content.html.twig' %}

{% block page_title %}Tableau de bord{% endblock %}

{% block main %}

{{ articleCount }}

Articles publies

{# ... autres cartes de statistiques #}
{% endblock %}

Integration avec les migrations Doctrine

EasyAdmin travaille directement avec vos entites Doctrine. Quand vous modifiez une entite, generez et executez la migration correspondante. Le guide des migrations Doctrine couvre ce workflow en detail.

Limites et alternatives

EasyAdmin excelle pour les back-offices standards. Ses limites apparaissent quand vous avez besoin de workflows complexes (machines a etats avec validations multi-niveaux), de dashboards en temps reel, ou d'interfaces tres specifiques. Dans ces cas, EasyAdmin sert de base que vous completez avec des controllers Symfony classiques. Pour les projets qui necessitent une API d'administration, API Platform + un front React ou Vue est une alternative a considerer.

Aller plus loin

EasyAdmin transforme Symfony en outil de productivite. En une heure, vous avez un back-office fonctionnel, securise et extensible. Pour completer votre back-office, explorez la securite Symfony pour affiner les permissions, le guide des FormTypes pour les formulaires complexes, et les migrations Doctrine pour la gestion du schema.

Vous souhaitez un back-office Symfony sur mesure ? Decouvrez mes services et tarifs, puis contactez-moi. Je developpe des back-offices EasyAdmin professionnels pour des clients en France et en Belgique.

Questions fréquentes

13 projets livrésGrand-Est & BelgiqueLighthouse >90Disponible immédiatement

Un projet en tête ?

Discutons de votre site web. Réponse garantie sous 24h.

Ou appelez directement :06 95 41 30 25

WhatsApp
Appeler