Service Providers & Dependency Injection

Service Providers

Service providers are the central place to register application services, bindings, and event listeners. They are stored in app/Providers.

  • Use service providers to bind interfaces to implementations, register singletons, and configure third-party packages.
  • Split custom logic into multiple providers for clarity (e.g., AppServiceProvider, AuthServiceProvider, EventServiceProvider).
  • Register providers in config/app.php under the providers array.

Example: Registering a binding

public function register()
{
    $this->app->bind(UserRepositoryInterface::class, UserRepository::class);
}

Dependency Injection

Dependency injection allows you to automatically resolve class dependencies. Use constructor injection for controllers, services, and jobs.

  • Prefer interfaces for type-hinting to allow flexibility and easier testing.
  • Use Laravel's automatic resolution for dependencies in controllers and jobs.

Example: Controller injection

class UserController extends Controller
{
    protected $users;
    public function __construct(UserRepositoryInterface $users)
    {
        $this->users = $users;
    }
}

Singleton vs Transient

  • Register singletons for shared services that should only have one instance per request lifecycle:
    $this->app->singleton(CacheService::class, function ($app) {
      return new CacheService();
    });
  • Register transient bindings for services that should be resolved fresh each time:
    $this->app->bind(NotificationService::class, function ($app) {
      return new NotificationService();
    });

Best Practices

  • Use dependency injection for all services and repositories.
  • Avoid using the app() helper or service container directly in controllers.
  • Document service provider logic with comments.
  • Use interfaces for all injected dependencies to improve testability.
  • Keep service providers focused and avoid mixing unrelated logic.

Example: Custom Service Provider

class CustomServiceProvider extends ServiceProvider
{
    public function register()
    {
        $this->app->singleton(CustomService::class, function ($app) {
            return new CustomService();
        });
    }
    public function boot()
    {
        // Boot logic, e.g., event listeners
    }
}