Utilisation de GridBundle sans Sylius

Table des matières
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é.

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.

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

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.

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...

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.

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".

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é:


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.

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:

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.

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)

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