Development › Dependency Injection
Dependency Injection
Use Laravel’s service container for all infrastructure and cross-cutting dependencies. Prefer constructor injection.
#Core contracts
Shared abstractions live under app/Core/Contracts:
| Contract | Responsibility |
|---|---|
EventBus | Publish domain/integration events |
CacheStore | Application-level cache access |
DistributedLock | Cross-process locking (Redis) |
IdempotencyStore | Consumer / request idempotency keys |
Bind implementations in service providers (AppServiceProvider or dedicated Infrastructure providers).
#Module bindings
Each module provider registers its own contracts:
public function register(): void
{
class="tk-v">$this->app->bind(
OrderRepository::class,
EloquentOrderRepository::class,
);
}Application Actions receive contracts, not concrete Eloquent classes:
final class CreateOrder
{
public function __construct(
private readonly OrderRepository class="tk-v">$orders,
private readonly EventBus class="tk-v">$eventBus,
) {}
}#Rules
- Never
newinfrastructure clients inside Actions or Domain code. - Bind interface → implementation once in a provider.
- Prefer
finalActions/DTOs; keep constructors explicit. - In tests, bind fakes/mocks of contracts instead of hitting Redis/Kafka.
- When extracting a microservice, keep the same contracts; swap only the provider bindings / transport.
#Contextual binding (optional)
Use contextual binding when two modules need different implementations of the same shared contract. Prefer module-local contracts when the semantics diverge.