danielm/symfony-demo-bundle
Demo Symfony bundle showing common bundle features: console command, services/contracts, events/subscriber, Twig extension, controllers with JSON/HTML routes, config with env vars, translations and public assets. Useful as a Symfony Flex recipe/demo reference.
Installation
composer require danielm/symfony-demo-bundle
If not using Flex, manually register the bundle in config/bundles.php:
return [
// ...
DanielM\DemoBundle\DanielMDemoBundle::class => ['all' => true],
];
First Use Case: Console Command Run the demo command to verify installation:
php bin/console demo:command
Expected output: Hello from DanielM\DemoBundle\Command\DemoCommand!
First Use Case: Twig Extension
Use the demoFcn() Twig function in a template:
{{ demoFcn() }}
Expected output: Hello from Twig!
First Use Case: Controller Endpoints Test the routes:
GET /{a}/{b} → Returns JSON with a + b.GET /view → Renders a Twig template.GET /dispatch/{md5_hash} → Dispatches UnnecessaryEvent (useful for testing events).Service Contracts/Adapters
DemoServiceInterface in your own service:
use DanielM\DemoBundle\Service\DemoServiceInterface;
class MyService implements DemoServiceInterface {
public function doSomething(string $input): string {
return "Processed: $input";
}
}
services.yaml:
services:
DanielM\DemoBundle\Service\DemoServiceInterface: '@my_service'
Events and Subscribers
$event = new UnnecessaryEvent($data);
$this->eventDispatcher->dispatch($event);
DemoSubscriber or creating a new subscriber:
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use DanielM\DemoBundle\Event\UnnecessaryEvent;
class MySubscriber implements EventSubscriberInterface {
public static function getSubscribedEvents(): array {
return [
UnnecessaryEvent::class => 'onUnnecessaryEvent',
];
}
public function onUnnecessaryEvent(UnnecessaryEvent $event) {
// Handle event logic
}
}
Configuration
$this->container->getParameter('danielm_demo.sample_config');
config/packages/danielm_demo.yaml:
danielm_demo:
sample_config: 'custom_value'
sample_env: '%env(DEMO_SAMPLE_ENV)%'
Twig Extensions
DemoTwigExtension or create a new extension:
use Twig\Extension\AbstractExtension;
use Twig\TwigFunction;
class MyTwigExtension extends AbstractExtension {
public function getFunctions(): array {
return [
new TwigFunction('myCustomFunction', [$this, 'customFunction']),
];
}
public function customFunction(): string {
return "Custom Twig Output";
}
}
Assets and Translations
assets/ directory (Symfony Flex auto-registers them).{{ 'demo.message'|trans }}
translations/messages.en.yaml:
demo:
message: "Custom translated message"
Dependency Injection
public function __construct(private DemoServiceInterface $demoService) {}
Testing
$this->container->set(DemoServiceInterface::class, $this->createMock(DemoServiceInterface::class));
Flex Recipes
Environment Variables
.env for sensitive/configurable values:
DEMO_SAMPLE_ENV=custom_value
Event Dispatching
UnnecessaryEvent are not automatically dispatched. You must manually trigger them in your code.Configuration Overrides
danielm_demo.yaml is missing, Symfony will throw a ParameterNotFoundException. Ensure the file exists even if empty:
# config/packages/danielm_demo.yaml
danielm_demo: {}
Twig Auto-Reloading
php bin/console cache:clear
Console Command Naming
demo:command are not auto-discovered in Laravel (this is a Symfony bundle). In Laravel, use:
php artisan demo:command
Or register it via App\Providers\CommandServiceProvider.Route Conflicts
/{a}/{b}, /view, etc.) may conflict with existing routes. Prefix them in config/routes.yaml:
danielm_demo:
resource: "@DanielMDemoBundle/Resources/config/routes.yaml"
prefix: "/demo"
Check Event Subscribers
php bin/console debug:event-dispatcher
UnnecessaryEvent in the output.Inspect Service Bindings
php bin/console debug:container | grep DemoService
Environment Variables
.env values:
php bin/console debug:config danielm_demo
Twig Debugging
config/packages/twig.yaml:
twig:
debug: '%kernel.debug%'
strict_variables: '%kernel.debug%'
Add New Services
DemoServiceInterface or create new interfaces in your own bundle.Custom Events
Symfony\Component\EventDispatcher\Event:
class MyCustomEvent extends Event {
public function __construct(private string $data) {}
public function getData(): string { return $this->data; }
}
Override Twig Functions
DemoTwigExtension by binding your own extension:
# config/services.yaml
services:
Twig\Extension\DemoTwigExtension: '@my_custom_twig_extension'
Modify Console Commands
DemoCommand or create a new command:
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
class MyCommand extends Command {
protected function execute(InputInterface $input, OutputInterface $output): int {
$output->writeln('Custom command output');
return Command::SUCCESS;
}
}
Asset Customization
vendor/danielm/demo-bundle/Resources/public to public/bundles/danielm_demo.Bundle Registration
config/app.php under extra.bundles.php:
'bundles' => [
DanielM\DemoBundle\DanielMDemoBundle::class => true,
],
Route Prefixing
routes/web.php:
Route::prefix('demo')->group(function () {
// Laravel routes here (avoid conflicts with Symfony routes)
});
Service Container Integration
AppServiceProvider:
public function register() {
$this->app->singleton(DemoServiceInterface::class, function ($app) {
return new MyService();
});
}
Event Dispatcher
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
$dispatcher = $this->app->make(EventDispatcherInterface::class);
$dispatcher->dispatch(new
How can I help you explore Laravel packages today?