Installation Add the package via Composer:
composer require cybernodev/framework-bundle
Register the bundle in config/bundles.php:
return [
// ...
Cybernodev\FrameworkBundle\FrameworkBundle::class => ['all' => true],
];
Verify Integration Check if the bundle loads by inspecting Symfony’s kernel events or running:
php bin/console debug:container | grep framework
(Note: Since this is a minimal package, verify via Symfony’s built-in debug tools.)
First Use Case
Use the bundle to extend Symfony’s core functionality (e.g., customizing request/response handling, event listeners, or service overrides).
Example: Override a Symfony service (e.g., router or http_kernel) via config/services.yaml:
services:
App\Custom\Router:
decorates: router
arguments: ['@App\Custom\Router.inner']
Service Overrides
Leverage the bundle to decorate or replace Symfony services without modifying core files.
Example: Extend the HttpKernel to add middleware:
// src/Service/HttpKernelDecorator.php
namespace App\Service;
use Symfony\Component\HttpKernel\HttpKernelInterface;
class HttpKernelDecorator implements HttpKernelInterface
{
private $inner;
public function __construct(HttpKernelInterface $inner) {
$this->inner = $inner;
}
public function handle($request, $type = HttpKernelInterface::MAIN_REQUEST, $catch = true) {
// Pre-processing logic
$response = $this->inner->handle($request, $type, $catch);
// Post-processing logic
return $response;
}
}
Register in services.yaml:
services:
App\Service\HttpKernelDecorator:
decorates: http_kernel
arguments: ['@App\Service\HttpKernelDecorator.inner']
Event Listeners/Subscribers
Use Symfony’s event system to hook into the framework lifecycle (e.g., kernel.request, kernel.response).
Example:
// src/EventListener/CustomResponseListener.php
namespace App\EventListener;
use Symfony\Component\HttpKernel\Event\ResponseEvent;
class CustomResponseListener
{
public function onKernelResponse(ResponseEvent $event) {
$event->getResponse()->headers->set('X-Custom-Header', 'value');
}
}
Register in services.yaml:
services:
App\EventListener\CustomResponseListener:
tags: ['kernel.event_listener', 'method: onKernelResponse', 'event: kernel.response']
Configuration Overrides
Extend Symfony’s default configuration via config/packages/framework.yaml:
framework:
router:
resource: "%kernel.project_dir%/config/routes.yaml"
strict_requirements: ~
http_client:
base_uri: "https://api.example.com"
php bin/console debug:event-dispatcher to inspect events.$this->container->set('router', $this->createMock(HttpKernelInterface::class));
Bundle Conflicts
FrameworkBundle), ensure your overrides are explicitly registered in services.yaml with higher priority.public: true or autowire: false to force resolution.Event Ordering
priority tags to control execution sequence:
tags: ['kernel.event_listener', 'method: onKernelRequest', 'event: kernel.request', 'priority: 255']
Circular Dependencies
router and http_kernel) may cause issues. Use interface segregation or lazy-loading.Configuration Merging
framework.yaml may overwrite Symfony defaults. Use merge or extend where possible:
framework:
router:
extend: true # Preserves existing config
php bin/console debug:container App\Service\HttpKernelDecorator
php bin/console debug:event-dispatcher
use Psr\Log\LoggerInterface;
class DebugMiddleware implements MiddlewareInterface
{
public function __construct(private LoggerInterface $logger) {}
public function handle(Request $request, callable $next): Response {
$this->logger->info('Request:', ['uri' => $request->getUri()]);
$response = $next($request);
$this->logger->info('Response:', ['status' => $response->getStatusCode()]);
return $response;
}
}
Custom Compiler Passes Use Symfony’s dependency injection compiler passes to modify services at compile time:
// src/DependencyInjection/Compiler/FrameworkPass.php
namespace App\DependencyInjection\Compiler;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
class FrameworkPass implements CompilerPassInterface
{
public function process(ContainerBuilder $container) {
if ($container->has('router')) {
$definition = $container->findDefinition('router');
$definition->addMethodCall('setCustomOption', ['value']);
}
}
}
Register in FrameworkBundle.php:
public function build(ContainerBuilder $container) {
$container->addCompilerPass(new FrameworkPass());
}
Twig Extensions Extend Twig templates via the bundle’s service integration:
// src/Twig/AppExtension.php
namespace App\Twig;
class AppExtension extends \Twig\Extension\AbstractExtension
{
public function getFunctions() {
return [
new \Twig\TwigFunction('custom_function', [$this, 'customFunction']),
];
}
public function customFunction() {
return 'Hello from custom Twig!';
}
}
Register in services.yaml:
services:
App\Twig\AppExtension:
tags: ['twig.extension']
Console Commands Integrate custom commands with Symfony’s CLI:
// src/Command/CustomCommand.php
namespace App\Command;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
class CustomCommand extends Command
{
protected static $defaultName = 'app:custom';
protected function execute(InputInterface $input, OutputInterface $output) {
$output->writeln('Custom command executed!');
}
}
No additional registration needed (automatically discovered by Symfony).
How can I help you explore Laravel packages today?