Trucs et astuces
En bonne feignasse, quand j'ai besoin d'un nouvel outil, je cherche d'abord si quelque chose existe.
Puis, en bonne développeuse exigeante, si rien n'existe ou si l'existant ne correspond pas à mes attentes, je développe mon propre outil.
C'est ainsi qu'est né phpBlocNote il y a des années.
Bien sûr, au fil du temps, il a (beaucoup) évolué. Mon instance perso porte même un autre nom (non, je ne vous le dirai pas, bande de petits curieux ^^).
Cet outil m'a aussi beaucoup servi de "base d'essai" pour tester des frameworks (oui, plusieurs en plus de 15 ans)
puis pour éprouver les montées de versions du framework gagnant (Symfony, en version 6.1 à l'heure où j'écris).
Puis, d'autres outils se sont ajoutés... j'ai aujourd'hui 7 web apps sur la même instance de Symfony !
Et depuis un certain temps, je voulais en faire des bundles, histoire de séparer, organiser proprement tout mon petit bazar (car aucune app n'a vraiment de lien avec ses copines).
Depuis que j'ai migré en Symfony 5, la volonté de "bundliser" mes apps (qui n'étaient que 3 à l'époque) revient régulièrement...
Mais faute de temps (ou de motivation), je ne m'y suis réellement collée que ces derniers jours. Et comme j'en ai ch*é, je me suis dit que, tant qu'à faire,
j'allais partager le résultat. Qui sait, ça peut servir à d'autres ;)
Dans cet exemple, le bundle est relativement simple mais comprend notamment des templates, quelques assets, des traductions et forcément, le routing.
J'ai consulté la documentation officielle Symfony concernant les bundles.
Mais cette documentation ne m'a pas permis, à elle seule, de créer et rendre mon bundle fonctionnel.
Après avoir pas mal tâtonné pour trouver une structure de fichiers fonctionnelle, voici à quoi je suis arrivée :
Vous reconnaîtrez sans doute l'arborescence standard d'un projet Symfony.
Comme j'aurai, à terme, plusieurs bundles, j'ai choisi d'ajouter un niveau "organisation" ou "vendor" (DelPlop), mais je pense qu'on peut s'en passer.
Ce répertoire principal se place à la racine du projet.
Le code du bundle se place dans un sous-répertoire du nom du bundle avec le suffixe (WishListBundle).
Enfin, la structure est celle d'un projet Symfony classique, telle que mentionnée dans
la documentation officielle.
Pour cette partie, je n'ai pas eu vraiment de souci (à part avoir voulu faire un truc bien compliqué en premier lieu ><), la documentation officielle présente une solution simple et efficace.
<?php declare(strict_types=1); namespace DelPlop\WishListBundle; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator; use Symfony\Component\HttpKernel\Bundle\AbstractBundle; class DelPlopWishListBundle extends AbstractBundle { public function prependExtension(ContainerConfigurator $container, ContainerBuilder $builder): void { $container->import('../config/services.yaml'); } }Et le contenu de config/services.yaml :
services: _defaults: autowire: true autoconfigure: true DelPlop\WishListBundle\: resource: '../src/' exclude: - '../src/Entity/' DelPlop\WishListBundle\Controller\: resource: '../src/Controller' tags: [ 'controller.service_arguments' ]
C'est probablement la partie qui m'a le plus bloquée et pourtant, ça semble si logique une fois fait ><
Composer sera votre ami. Il faut éditer le fichier composer.json à la racine du projet puis en créer un dans le bundle (à la racine également).
[...] "repositories": [ { "type": "path", "url": "DelPlop/WishListBundle" } ], "require": { "delplop/wishlist-bundle": "dev-master" }Le fichier composer.json du bundle :
{ "name": "delplop/wishlist-bundle", "description": "My Wish-list Symfony bundle", "type": "symfony-bundle", "require": { "php": ">=8.1", "symfony/framework-bundle": "6.1.*" }, "autoload": { "psr-4": { "DelPlop\\WishListBundle\\": "src/" } }, "license": "proprietary", "authors": [ { "name": "Del Plop", "email": "<votre email>" } ] }Bien sûr, ajustez selon vos goûts (licence, nom du ou des auteurs, description, etc) ; veillez simplement à ce que le nom corresponde à ce que vous ajoutez dans le fichier composer.json du projet.
composer updateEt on est presque prêt ;)
<?php declare(strict_types=1); namespace DelPlop\WishListBundle\Controller; use DelPlop\WishListBundle\Repository\WishListUserRepository; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Response; class UserController extends AbstractController { public function index(WishListUserRepository $wishListUserRepository): Response { return $this->render('@DelPlopWishList/user/list.html.twig', [ 'users' => $wishListUserRepository->findAll() ]); } }Le template associé :
{% extends '@DelPlopWishList/wishlist.html.twig' %} {% trans_default_domain 'wishlist' %} {% block title %}{{ ('users.list_long'|trans) }}{% endblock %} {% block body %} <h1 class="w3-card-4 w3-padding-16">{{ ('users.list_long'|trans) }}</h1> <table class="w3-table w3-striped w3-bordered"> <tr class="w3-theme"> <th>{{ ('users.name'|trans) }}</th> </tr> {% for user in users %} <tr> <td> <a href="{{ path('wishlist_user_articles', {id: user.id}) }}" title="{{ ('articles.see_user_articles'|trans({username: user.user.username})) }}">{{ user.user.username }}</a> </td> </tr> {% endfor %} </table> {% endblock %}Rien d'extraordinaire là-dedans.
wishlist_routes: name_prefix: 'wishlist_' resource: '@DelPlopWishListBundle/config/routes.yaml'
Après avoir lancé bin/console assets:install, les assets du bundle se trouvent dans public/bundles/delplopwishlist/.