Introduction
Symfony is built around a simple but powerful idea: everything is a bundle. A bundle is a self-contained package of code — controllers, entities, services, and templates — that can be reused across multiple projects.
In this guide, we’ll walk through how bundles work, how to create your own, and how they fit into a modern Symfony 7 application.
What Is a Bundle?
In Symfony, a bundle is similar to a plugin in other frameworks, but more structured. Bundles can contain anything: configuration, routes, services, entities, forms, and templates. Each bundle is represented by a PHP class that extends Symfony\Component\HttpKernel\Bundle\Bundle.
// src/CustomerBundle/CustomerBundle.php
namespace App\CustomerBundle;
use Symfony\Component\HttpKernel\Bundle\Bundle;
class CustomerBundle extends Bundle
{
}
The presence of this class tells Symfony that this directory is a bundle that should be bootstrapped during the kernel initialization.
Bundle Folder Structure
A typical bundle mirrors the structure of a full Symfony app:
src/
└── CustomerBundle/
├── Controller/
│ └── CustomerController.php
├── Entity/
│ └── Customer.php
├── Repository/
│ └── CustomerRepository.php
├── Resources/
│ ├── config/
│ │ └── routes.yaml
│ └── views/
│ └── customer/
│ └── list.html.twig
├── Service/
│ └── CustomerNotifier.php
└── CustomerBundle.php
Everything related to customer management — code, templates, configuration — lives neatly inside its own namespace.
Creating a Controller Inside Your Bundle
Let’s add a simple controller that lists all customers.
// src/CustomerBundle/Controller/CustomerController.php
namespace App\CustomerBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
#[Route('/customers')]
class CustomerController extends AbstractController
{
#[Route('/', name: 'customer_list')]
public function list(): Response
{
// In a real app, you'd fetch this from the database
$customers = [
['name' => 'Alice', 'email' => 'alice@example.com'],
['name' => 'Bob', 'email' => 'bob@example.com'],
];
return $this->render('@Customer/customer/list.html.twig', [
'customers' => $customers,
]);
}
}
The Twig template lives inside the bundle under: Resources/views/customer/list.html.twig
Example Twig Template
{# src/CustomerBundle/Resources/views/customer/list.html.twig #}
Customer List
{% for customer in customers %}
{{ customer.name }} — {{ customer.email }}
{% endfor %}
Symfony automatically resolves @Customer to your bundle’s view path, thanks to the bundle namespace registration.
Registering Your Bundle
In Symfony 7, bundles can be registered automatically using Symfony Flex. If you need to register it manually, open config/bundles.php:
// config/bundles.php
return [
Symfony\Bundle\FrameworkBundle\FrameworkBundle::class => ['all' => true],
App\CustomerBundle\CustomerBundle::class => ['all' => true],
];
Once registered, Symfony treats it as a first-class part of your application.
Adding Services to Your Bundle
Services inside the bundle can be auto-configured and autowired using a services.yaml file:
# src/CustomerBundle/Resources/config/services.yaml
services:
App\CustomerBundle\:
resource: '../../*'
exclude: '../../{Entity,Tests,Resources}'
autowire: true
autoconfigure: true
Then import this file from your main configuration:
# config/services.yaml
imports:
- { resource: '@Customer/Resources/config/services.yaml' }
Reusing Your Bundle Across Projects
The real magic of bundles appears when you start reusing them. You can move src/CustomerBundle into its own repository, add a composer.json, and install it like any PHP package.
{
"name": "acme/customer-bundle",
"type": "symfony-bundle",
"autoload": {
"psr-4": { "Acme\\CustomerBundle\\": "" }
},
"require": {
"php": ">=8.2",
"symfony/framework-bundle": "^7.0"
}
}
After publishing it to Packagist or GitHub, you (or others) can reuse it in any Symfony project:
composer require acme/customer-bundle
Conclusion
Bundles are one of Symfony’s most powerful concepts. They help you organize code logically, promote reuse, and maintain clean architecture. By structuring features as independent bundles, your applications become modular and scalable by design.
Whether you’re building a small app or a complex CRM, bundles will keep your Symfony projects elegant, consistent, and easy to maintain.