Utilisation de GridBundle sans Sylius

Par @jbnahan69
Le résultat final

Dans le premier article, j'ai démarré un projet Symfony avec comme but d'utiliser des bundles Sylius sans la partie e-commerce. J'y ai installé le SyliusThemeBundle.

Dans le second article, j'ai continué le projet en installant le SyliusUIBundle. Ce bundle n'est pas prévu pour être utilisé hors de Sylius et m'a demandé un peu de rétro ingénierie pour qu'il fonctionne correctement.

Dans ce troisième article, je vais utiliser SyliusGridBundle. Ce bundle est prévu pour être utilisé en dehors de Sylius mais conjointement avec le SyliusResourceBundle. SyliusGridBundle permet la gestion simple (via de la configuration) de grille de données avec pagination, tri, filtre, actions globales, actions groupées ou action pour une ligne de données.

L'absence du SyliusResourceBundle, m'a posé de nombreux de problème et j'ai encore une fois réalisé de l'ingénierie inverse pour comprendre comment cela fonctionne.

Dans le métier de développeur, il est très important de savoir décortiquer le fonctionnement d'un logiciel pour pouvoir le modifier. Avoir accès au code source des logiciels PHP est un ajout majeur qui nous évite de devoir utiliser d'autre outils parfois plus complexe à prendre en main.

Comme pour la première étape, j'ai réalisé un thread twitter pour vous partager mon avancé. Si les thread vous intéressent, suivez moi sur Twitter.

Dans cet article, je vais reprendre les grandes étapes et les erreurs les plus difficiles à résoudre. Le but étant d'afficher une grille de données, il est nécessaire d'avoir une base de données et des données. Pour cela, le projet sera un Blog.

Ajouter une entité doctrine

Pour aller vite, j'ai utilisé la commande bin/console make:entity BlogPost pour initialiser mon entité.

L'entité générée par le Maker

Pour gérer les dates de création et de mise à jour, j'utiliser les fonctions de rappel (callback) lié a la vie de l'entité. A savoir PrePersist et PreUpdate.

J'ai transformé les setter en fonction de rappel Doctrine.

Pour terminé, il est obligatoire de générer une migration Doctrine avec la commande bin/console doctrine:migrations:diff et de l'exécuter avec la commande bin/console doctrine:migrations:migrate

La classe de migration de la base SQLite

Le projet est maintenant prêt pour afficher la liste des blog posts.

Installation du bundle

Comme pour toute dépendance directe d'un projet, l'installation est réalisé par la commande composer req sylius/grid-bundle

Il n'y a rien a installé car c'est une dépendance obligatoire de SyliusUiBundle.

Cependant, j'ai eu plus tard une erreur lié a une dépendance manquante : PagerFanta.

L'erreur fut double car j'avais installé en premier lieu la version 3 alors que le Sylius utilise encore la version 2.

Pour finir voici les dépendances obligatoires non installées avec le Bundle :

composer req babdev/pagerfanta-bundle ^2.0 pagerfanta/pagerfanta ^2.0 pagerfanta/twig ^2.0

Configuration de la grille

La configuration d'une grille se fait exclusivement dans un fichier de configuration YAML. En se basant sur la documentation, la configuration est aisée.

Définition de la grille

Etant donné que le ResourceBundle n'est pas installé, je dois définir tous les détails de chaque action : nom de la route, paramètres...

Configuration des actions

Définition des routes

En l'absence du ResourceBundle (oui il facilite énormément la vie), je doit donc définir manuellement chaque route nécessaire pour ma ressource.

Définition des routes sans contrôleur

Les contrôleurs ne sont pas défini car je ne vais pas les utiliser. Le GridBundle a besoin de générer les URL.

Le contrôleur pour l'index

La page d'affichage de la grille correspond à l'index (le listing) et j'ai besoin d'un contrôleur pour la route app_blog_post_index.

J'ajoute donc la classe BlogPostIndexController avec un affichage d'un template vide pour l'instant.

Pour ajouter l'affichage de la grille, je me suis basé sur le projet Sylius 1.10 pour remonter jusqu'à l'appel de la fonction Twig "sylius_grid_render".

L'appel de la fonction Twig "sylius_grid_render" dans le projet Sylius.

J'ai ensuite eu de nombreuses erreurs sur les données fournis, la méthode du repository qui ne retournait pas un QueryBuilder, et enfin, j'ai obtenu ce contrôleur:

<?php

namespace App\Controller;

use Sylius\Component\Grid\Parameters;
use Sylius\Component\Grid\Provider\GridProviderInterface;
use Sylius\Component\Grid\View\GridViewFactoryInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;

class BlogPostIndexController extends AbstractController
{
    public function __invoke(
        Request               $request,
        GridProviderInterface $gridProvider,
        GridViewFactoryInterface $gridViewFactory
    )
    {
        $gridView = $gridViewFactory->create(
            $gridProvider->get('app_blog_post'),
            new Parameters($request->query->all())
        ) ;


        return $this->render('blogpost/index.html.twig', [
            'resources' => $gridView,
        ]);
    }
}

La configuration de la grille et le repository ont également changé:

Configuration de la grille correcte pour l'obtention du QueryBuilder.
La fonction dans le Respository.

Le menu

Pour permettre un accès aisé à la page de listing des blog post, j'ai modifié le menu principal pour y mettre un lien directe vers la page.

La configuration du lien dans le menu princial.

Lors de l'ajout de l'UiBundle dans le projet, j'avais également configuré un menu principal pour que l'apparence du site soit similaire à celle de Sylius.

Les templates

Le template de la page de listing des blog post est réduite au maximum. Lors de l'affichage des première tentative d'affichage j'ai eu des problèmes de template pour les actions. Aucune d'elles n'est définie.

J'ai dû copier et modifié les templates de Sylius présents dans l'AdminBundle :

{% import '@SyliusUi/Macro/buttons.html.twig' as buttons %}
{% set options = action.options %}
{% set path = options.link.url|default(path(options.link.route, options.link.parameters|default({'id': data.id}))) %}

{{ buttons.delete(path, action.label, true, data.id) }}

puis les configurer:

sylius_grid:
  templates:
    action:
      update: "Grid/Action/update.html.twig"
      delete: "Grid/Action/delete.html.twig"
      show: "Grid/Action/show.html.twig"

L'affichage de cette première page fut satisfaisante:

Aucune données a afficher.

L'ajout des données

Maintenant que la page sans données s'affiche, il est nécessaire d'ajouter des données dans la base de données.

Pour n'importe quel projet, j'aurais utilisé des Fixtures pour charger les données. Mais par manque de temps, j'ai préférer utiliser le contrôleur Home (ajouté lors du démarrage du projet) pour initialiser des BlogPost et les sauvegarder en base de données.

Ajout de données dans la base de données grâce à un contrôleur.

Conclusion

Pour conclure, cette étape s’annonçait plus simple de par la connaissance que j'en avais. Mais l'absence du ResourceBundle m'a fait comprendre que ces deux Bundles sont très puissants ensemble.

J'aurai sûrement gagné du temps en les utilisant conjointement, mais je n'aurais pas appris son fonctionnement interne.

Tous le travail que j'ai réalisé et que je vous ai décris au cours de ces 3 articles avait déjà été réalisé. Tout ce travail est rassembler dans le projet Monofony. Je pourrais en faire un article de présentation si cela vous intéressent (dite le sur Twitter)

La liste des blogs posts terminés.

Le code source du projet est disponible sur le dépôt GitHub du Hack de Sylius.

Author avatar
Jean-Baptiste Nahan

Consultant Expert Web, j'aide les entreprises ayant des difficultés avec leur projet Web (PHP, Symfony, Sylius).

@jbnahan69 | Macintoshplus | Linkedin | JB Dev Labs