Le 13 novembre 2025, par Joris Vinière.
Bundle PHP / Symfony : aller plus loin
Introduction
Un bundle est une extension applicative (plugin), il a pour objectif d'ajouter des fonctionnalités techniques qui répondent à un périmètre défini. Il est composé d'un ensemble de fichiers structurés, voir notre précédent article.
Dans cet article, nous allons vous montrer comment rendre paramétrable un bundle et afficher son nom et sa version dans le Profiler Symfony de votre application.

Pour ce faire, nous devrons tout d'abord modifier la classe bundle afin d'y ajouter une partie configuration. Bien que vide par défaut, cette classe est pratique et permet de personnaliser le comportement du bundle. Il nous faudra ensuite créer un fichier de configuration dans notre application qui sera utilisé pour le bundle. Enfin nous terminerons par l'utilisation des DataCollector de Symfony afin de pouvoir afficher les informations que nous voulons dans le profiler.
Dans un premier temps, notre objectif va être de définir la configuration possible de notre bundle, nous allons donc utiliser la fonction "configure" :
// src/HelloWorldBundle.php
<?php
namespace IDCI\Bundle\HelloWorldBundle;
use Symfony\Component\Config\Definition\Configurator\DefinitionConfigurator;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
use Symfony\Component\HttpKernel\Bundle\AbstractBundle;
class HelloWorldBundle extends AbstractBundle
{
public function configure(DefinitionConfigurator $definition): void
{
$definition->rootNode()
->children()
->arrayNode('app')
->isRequired()
->children()
->scalarNode('name')->isRequired()->end()
->scalarNode('version')->isRequired()->end()
->end()
->end()
->end()
;
}
}
Plusieurs notions sont assez importantes dans le code ci-dessus, nous allons les détailler.
La méthode configure() sert à définir ou importer depuis un ou plusieurs fichiers, la configuration possible du bundle. Cette méthode utilise le TreeBuilder de Symfony, qui permet d'organiser de manière hiérarchique les paramètres attendus par notre bundle.
Dans notre cas, nous indiquons que le bundle requiert plusieurs paramètres :
- name sous la clé de configuration app
- version sous la clé de configuration app
Nous pouvons donc ajouter le fichier de configuration du bundle dans notre application :
// YourApp/config/packages/idci_hello_world.yaml
hello_world:
app:
name: HelloWorld
version: 1.0.0
Les valeurs attribuées aux paramètres sont libres, cependant nous utilisons la convention de nommage Semantic Versioning. L'idée générale est de nommer sa version d'après la strucutre X.Y.Z où X représente un changement majeur, Y un changement mineur et Z un correctif. Pour la première version nous choississons donc 1.0.0 .
Nous allons maintenant associer les valeurs définies de la configuration du bundle à des paramètres dans le conteneur d'injection de dépendances :
// src/HelloWorldBundle.php
<?php
namespace IDCI\Bundle\HelloWorldBundle;
use Symfony\Component\Config\Definition\Configurator\DefinitionConfigurator;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
use Symfony\Component\HttpKernel\Bundle\AbstractBundle;
class HelloWorldBundle extends AbstractBundle
{
public function configure(DefinitionConfigurator $definition): void
{
$definition->rootNode()
->children()
->arrayNode('app')
->isRequired()
->children()
->scalarNode('name')->isRequired()->end()
->scalarNode('version')->isRequired()->end()
->end()
->end()
->end()
;
}
public function loadExtension(array $config, ContainerConfigurator $container, ContainerBuilder $builder): void
{
$builder->setParameter('hello_world_bundle.app_name', $config['app']['name']);
$builder->setParameter('hello_world_bundle.app_version', $config['app']['version']);
}
}
loadExtension() : Méthode appelée au moment de la compilation, permet de charger la définition de services à partir de fichiers de configuration.
Maintenant que nous avons ajouté la configuration, nous voulons nous assurer que les paramètres sont bien pris en compte. Pour ce faire, nous pouvons utiliser la commande suivante qui permet d'afficher les paramètres des services enregistrés :
php bin/console debug:container --parameters
On peux constater que nos 2 paramètres ont bien été pris en compte :

Pour la suite, nous allons voir comment utiliser les DataCollector de Symfony afin d'afficher des informations dans le Profiler :
<?php
namespace IDCI\Bundle\HelloWorldBundle\DataCollector;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\DataCollector\DataCollector;
class HelloWorldDataCollector extends DataCollector
{
public function __construct(
private string $appName,
private string $appVersion,
) {
}
public function collect(Request $request, Response $response, \Throwable $exception = null): void
{
$this->data['hello_world.app_name'] = $this->appName;
$this->data['hello_world.app_version'] = $this->appVersion;
}
public function reset(): void
{
$this->data = [];
}
public function getName(): string
{
return 'hello_world.data_collector';
}
public function getAppName(): string
{
return $this->data['hello_world.app_name'];
}
public function getAppVersion(): string
{
return $this->data['hello_world.app_version'];
}
}
collect(): Collecte les données dans les propriétés locales
reset(): Cette méthode est appelée entre chaque requêtes pour vider les informations contenues dans le Profiler.
getName(): Renvoie le nom du Collector (son identifiant). Ce nom doit être unique et il est préférable de le faire convenir aux conventions (court, en minuscule et sans espaces).
Nous ajoutons aussi 2 méthodes qui nous servirons à récupérer les 2 paramètres que nous voulons afficher dans le Profiler.
Il nous faut ensuite ajouter un fichier de template qui nous permettra de structurer l'affichage de ces informations.
{% extends '@WebProfiler/Profiler/layout.html.twig' %}
{% block toolbar %}
{% set icon %}
<img src="data:image/png;base64,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">
{% endset %}
{% set text %}
<div class="sf-toolbar-info-group">
<div class="sf-toolbar-info-piece">
<p>Nom : {{ collector.appName }}</p>
<p>Version : {{ collector.appVersion }}</p>
</div>
</div>
{% endset %}
{{ include('@WebProfiler/Profiler/toolbar_item.html.twig', { link: true, name: 'hello_world.data_collector', additional_classes: 'sf-toolbar-block-right' }) }}
{% endblock %}
Nous allons maintenant pouvoir faire le lien entre notre DataCollector et notre template. Pour cela nous allons définir le service dans le fichiers services.yaml du bundle en précisant l'emplacement du template et en passant en arguments les paramètres du conteneur d'injection de dépendances créés précedemment.
// config/services.yaml
services:
IDCI\Bundle\HelloWorldBundle\DataCollector\HelloWorldDataCollector:
tags:
-
name: 'data_collector'
template: '@HelloWorld/collector/hello_world.html.twig'
id: 'hello_world.data_collector'
arguments:
$appName: '%hello_world_bundle.app_name%'
$appVersion: '%hello_world_bundle.app_version%'
Finalement, nous chargerons ce fichier de configuration via la classe bundle.
// src/HelloWorldBundle.php
<?php
namespace IDCI\Bundle\HelloWorldBundle;
use Symfony\Component\Config\Definition\Configurator\DefinitionConfigurator;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
use Symfony\Component\HttpKernel\Bundle\AbstractBundle;
class HelloWorldBundle extends AbstractBundle
{
public function configure(DefinitionConfigurator $definition): void
{
$definition->rootNode()
->children()
->arrayNode('app')
->isRequired()
->children()
->scalarNode('name')->isRequired()->end()
->scalarNode('version')->isRequired()->end()
->end()
->end()
->end()
;
}
public function loadExtension(array $config, ContainerConfigurator $container, ContainerBuilder $builder): void
{
$builder->setParameter('hello_world_bundle.app_name', $config['app']['name']);
$builder->setParameter('hello_world_bundle.app_version', $config['app']['version']);
$container->import('../config/services.yaml');
}
}
Avec ceci vous aurez accès aux informations de votre bundle dans le profiler de Symfony !


Voir l'exemple