symfony/dependency-injection
Symfony DependencyInjection standardizes and centralizes object construction with a powerful service container. Define, configure, and wire services, manage parameters and service lifecycles, and enable autowiring and compilation for efficient, testable apps.
Installation
composer require symfony/dependency-injection
Laravel already uses this under the hood (via Illuminate/Container), but standalone usage is possible.
First Use Case: Manual Container Initialization
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;
$container = new ContainerBuilder();
$container->register('app.service', MyService::class)
->setArguments([new Reference('app.other_service')]);
$container->register('app.other_service', OtherService::class);
$service = $container->get('app.service');
Where to Look First
Illuminate\Container\Container (for integration patterns)ContainerBuilder and Definition classes for core functionality.$container->autowire(MyService::class)
->setPublic(true) // Expose as a service
->setAutowired(true); // Enable autowiring
$definition = $container->register(MyListener::class);
$definition->addTag('kernel.event_listener', ['event' => 'app.event']);
$container = app();
$container->extend('app.service', function ($app, $service) {
$service->setConfig($app['config']['services']);
return $service;
});
$container = new ContainerBuilder();
// Register Laravel bindings manually...
$app = new LaravelApp($container);
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
class MyCompilerPass implements CompilerPassInterface {
public function process(ContainerBuilder $container) {
if (!$container->has('app.service')) return;
$definition = $container->findDefinition('app.service');
$definition->addMethodCall('setPostConfig', [['value' => 42]]);
}
}
Register via:
$container->addCompilerPass(new MyCompilerPass());
$container->setParameter('app.debug', env('APP_DEBUG', false));
$container->setParameter('app.services', [
'timeout' => 30,
]);
Access in services:
$debug = $container->getParameter('app.debug');
Circular Dependencies
CircularReferenceException. Use setLazy(true) or refactor.$definition->setLazy(true); // Lazy-load to break cycles
Autowiring Conflicts
$container->autowire(MyService::class)->setPublic(false);
Parameter Overrides
setParameter() replace existing ones. Use setParameterBag() for bulk updates.Service Not Found
setPublic(true). Use:$container->has('service.id'); // Verify existence
dump($container->getServiceIds());
dump($container->getDefinition('service.id'));
$container->setDebug(true); // Shows detailed errors
$container->set('app.locator', new class {
public function find($id) { /* custom logic */ }
});
$container->setDefinition('app.service', new Definition(MyService::class));
ContainerInterface for Read-Only Access
$container->get('service.id'); // No modifications allowed
app() and $container
Laravel’s app() is a ContainerInterface wrapper. Prefer direct $container usage for DI features.setPublic(false) to force Symfony DI resolution:
$container->register('app.service', MyService::class)->setPublic(false);
How can I help you explore Laravel packages today?