Dependency Injection (DI)
Overview
Quantum PHP Framework uses a powerful Dependency Injection system to manage class dependencies, lifecycle, and automatic wiring, enabling loose coupling and easier testing.
The DI system centers around three main classes:
Di: A static facade forwarding requests to the DI container in the app context.DiContainer: A container holding dependency registrations, resolved instances, and implementing the core logic.DiRegistry: Stores and validates dependency bindings.
Core Concepts
- Registration: Bind interfaces or abstract names to concrete classes.
- Resolution: Retrieve shared or new instances, recursively resolving their constructor dependencies.
- Autowiring: Use reflection to automatically supply constructor or callable parameters.
- Singleton Management: Cached instances returned for shared dependencies.
- Circular Dependency Detection: Prevent infinite recursion in dependency graphs.
Key API Methods
Di::register(string $concrete, ?string $abstract = null): Register a dependency.Di::get(string $abstract, array $args = []): Retrieve shared instance.Di::create(string $abstract, array $args = []): Create a new instance.Di::autowire(callable $callable, array $args = []): Autowire parameters for a callable. This method returns an array of resolved arguments and does not invoke the callable.
Usage:
$args = Di::autowire($callable, $inputArgs);
$callable(...$args);
Di::set(string $abstract, object $instance, bool $override = true): Manually set an instance, optionally preventing an override of existing registered instances by setting$overridetofalse. If the dependency is already registered andoverrideisfalse, the method throws an exception.
Usage Example
use Quantum\Di\Di;
// Register interface to class binding
Di::register(FooService::class, FooInterface::class);
// Get singleton instance
$foo = Di::get(FooInterface::class);
// Create new instance
$newFoo = Di::create(FooService::class);
// Autowire callable
Di::autowire(function(FooInterface $foo, BarService $bar) {
// Use injected dependencies
});
How It Works
DiContainerstores mappings and instances.- Upon
getorcreate, it resolves dependencies recursively using reflection. - Checks circular dependencies and throws exceptions if found.
- Uses
DiRegistryto validate and fetch concrete implementations.
Best Practices
- Register dependencies at application boot.
- Use interfaces for type-hinting to decouple code.
- Avoid circular references.
- Prefer autowiring with constructor injection.
What to read next
After DI concepts, continue with: