Je partage aujourd’hui un concept pas nouveau, mais souvent oublié par les développeurs.
Dans le cadre de notre travail, il nous a été demandé de développer des bundles qui vont être réutilisés sur d’autres projets et utiliser par d’autres boîtes qui bossent pour le même client.
Le challenge ici était de sortir ce qui a été fait et le mettre dans un bundle dédié, donc pas mal de factorisation du code, le rendre plus générique, ….
Au lieu d’aller créer un dépôt et commencer de développer ou mettre le code déjà implémenté, nous avons profité du composer, tout en créant un dossier package qui va contenir le bundle
Voici un exemple de comment faire :
Dans votre fichier composer.json
.... "autoload": { "psr-4": { "App\\": "src/", "Bundle\\TrackingBundle\\": "./packages/TrackingBundle/src" } }, ....
Le dossier package va contenir votre bundle avec son premier fichier README et son fichier composer.json dédié
Je parle ici dans un contexte (Ibexa3/Symfony5). Ibexa est DXP, CMS qui se base sur Symfony 5, donc coder avec Ibexa veut dire coder avec Symfony 5.
Parmi les premières choses qu’on a fait est utiliser la fonctionnalité
- https://doc.ibexa.co/en/master/guide/multisite/siteaccess_aware_configuration/ ===> SiteAccess-aware configuration
ça permet d’utiliser de la configuration par siteAccess. Comme vous le savez un CMS fournit cette fonctionnalité par défaut, siteAccess, afin d’avoir plusieurs sites sur la même instance. Du coup chaque site peut avoir sa propre configuration.
Ensuite au niveau du code du bundle. Ce dernier propose des services, le challenge ici, c’est que ces services devront proposer le max possible du besoin, mais ce qui n’est pas toujours le cas. Pour faire simple, nous avons créé des interfaces pour chaque service avec une implémentation par défaut. Si le besoin d’une boîte donnée qui va utiliser le bundle ne colle pas avec le service proposé, tout simplement ils peuvent implémenter l’interface afin de coder leur propre besoin. Ceci normalement on doit le faire sans attende une demande du client ou un développement dans un bundle spécifique, mais ce n’est pas toujours le cas
Voici quelques exemples
- Services
- Contracts
- InterfaceA
- InterfaceB
- ServiceA (implements InterfaceA)
- ServiceB (implements InterfaceB)
- Contracts
Avec la configuration par défaut du Symfony, tout rentre dans l’ordre
- https://symfony.com/doc/5.3/service_container/autowiring.html#working-with-interfaces
- When using a service definition prototype, if only one service is discovered that implements an interface, and that interface is also discovered in the same file, configuring the alias is not mandatory and Symfony will automatically create one.
Rien du nouveau, mais juste il faut vraiment prendre le temps pour la conception car c’est la clé.