Personnalisez le CRUD generator de Symfony2

Introduction

Symfony2 possède de base un générateur de CRUD accessible via la commande php app/console generate:doctrine:crud. Cependant le résultat obtenu, bien que fonctionnel, reste loin de ce qu'on a pu connaître avec l'admin generator de Symfony 1.4.

Cette commande génère un nouveau contrôleur permettant d'administrer une entité. Ce contrôleur dispose des actions permettant de lister, créer, modifier, supprimer et visualiser des entités mais dépouiller des toute autre fonctionnalité tel que des filtres ou la pagination des listes et sans aucune mise en page.

Dans un premier temps, nous créerons une commande qui héritera du générateur de Symfony2. Puis dans un second temps nous ajouterons des fonctionnalité à cette commande afin de personnaliser les admins générer.

Hériter de la commande

Dans un bundle de votre choix, créer un répertoire Command et placez y votre classe qui héritera de la commande Symfony2.

<?php

// src/Acme/Bundle/GeneratorBundle/Command/GenerateAdminCommand.php
namespace Acme\Bundle\GeneratorBundle\Command;

use Sensio\Bundle\GeneratorBundle\Command\GenerateDoctrineCrudCommand;
use Sensio\Bundle\GeneratorBundle\Generator\DoctrineCrudGenerator;

class GenerateAdminCommand extends GenerateDoctrineCrudCommand
{
    protected function configure()
    {
        parent::configure();
        $this->setName('acme:generate:admin');
        $this->setDescription('Admin generator');
    }

    protected function getGenerator()
    {
        if (null === $this->generator)
        {
            $this->generator = new DoctrineCrudGenerator($this->getContainer()->get('filesystem'), __DIR__.'/../Resources/skeleton/crud');
        }

        return $this->generator;
    }
}

Puis copier le répertoire /vendor/bundles/Sensio/Bundle/GeneratorBundle/Resources/skeleton dans les Resources de votre bundle. Ce répertoire contient les squelettes des fichiers générés par la commande.

Personnaliser les vues

C'est le repertoire /skeleton/crud/views qui va nous intéresser, il contient les squelettes des vues des différents actions CRUD.

  • index.html.twig affiche la liste des entités
  • show.html.twig affiche le détail d'un entité
  • new.html.twig affiche le formulaire de création d'une entité
  • edit.html.twig affiche le formulaire de modification d'une entité

Vous pouvez ajouter un layout, personnaliser les boutons et liens, ajouter des classes pour votre CSS, ...

// src/Acme/Bundle/GeneratorBundle/Resources/skeleton/views/index.html.twig

{{ "{% extends '::admin.html.twig' %}" }}

{{ "{% block content %}" }}

<h1>{{ entity }} list</h1>

<table class="records_list table table-bordered table-striped">
    <thead>
        <tr>
        {%- for field, metadata in fields %}
            <th>{{ field|capitalize }}</th>
        {%- endfor %}
            <th>Actions</th>
        </tr>
    </thead>
    <tbody>
    {{ '{% for entity in entities %}' }}
        <tr>

           // [...]

        </tr>
    {{ '{% endfor %}' }}
    </tbody>
</table>

{% if 'new' in actions %}
<ul class="inline">
    <li>
        <a href="{{ "{{ path('"~ route_name_prefix ~"_new') }}" }}" class="btn btn-success">
            Create a new entry
        </a>
    </li>
</ul>
{% endif %}

{{ "{% endblock %}" }}

Personnaliser les actions

Les squelettes des actions se trouvent dans le répertoire skeleton/crud/actions a raison d'un fichier par action. Le fichier skeleton/crud/controller.php contient le squelette du contrôleur.

Vous pouvez par exemple ajouter des messages flash (notice et error) indiquant la réussite ou l'échec de la création d'une entité. Pour cela, ajouter créez des messages flash dans l'action create (ligne 9 et 19).

// skeleton/crud/actions/create.php

 if ($form->isValid()) {
     $em = $this->getDoctrine()->getEntityManager();
     $em->persist($entity);
     $em->flush();

     // Flash de réussite
     $this->getRequest()->getSession()->setFlash('notice', 'The item was created successfully.');

     {% if 'show' in actions -%}
         return $this->redirect($this->generateUrl('{{ route_name_prefix }}_show', array('id' => $entity->getId())));
     {% else -%}
          return $this->redirect($this->generateUrl('{{ route_name_prefix }}'));
     {%- endif %}
}
else {
     // Flash d'erreur
     $this->getRequest()->getSession()->setFlash('error', 'The item has not been saved due to some errors.');
}

Puis ajoutez l'affichage des messages flash dans la vue skeleton/crud/view/create.html.twig.

{% if app.session.hasFlash('notice') %}
    <div class="alert alert-success">
        <a class="close" data-dismiss="alert" href="#">×</a>
        {{ app.session.flash('notice') }}
    </div>
{% endif %}

{% if app.session.hasFlash('error') %}
    <div class="alert alert-error">
        <a class="close" data-dismiss="alert" href="#">×</a>
        {{ app.session.flash('error') }}
    </div>
{% endif %}

Les commentaires