VOOZH about

URL: https://deepwiki.com/mathsgod/light/2.3-dependency-injection

⇱ Dependency Injection | mathsgod/light | DeepWiki


Loading...
Last indexed: 31 January 2026 (cf9511)
Menu

Dependency Injection

This page explains how the Light framework uses League Container for dependency injection (DI), including container initialization, service registration, and automatic dependency resolution. For information about the overall request processing flow, see Request Lifecycle.

Overview

The Light framework uses league/container (version 4.x) as its dependency injection container. The container manages object creation and lifetime, enabling automatic dependency resolution through constructor injection. All services, controllers, and framework components are managed by the container, providing a centralized point for dependency management.

Sources: src/App.php68 composer.lock1555-1635

Container Initialization

The dependency injection container is instantiated during Light\App construction and serves as the central registry for all framework services.


Sources: src/App.php59-147

Container Creation

The container is created as a standard League\Container\Container instance without delegation to a reflection container:

src/App.php68


The commented-out code at lines 99-101 shows that reflection-based auto-wiring was previously considered but is not currently used. Instead, all services are explicitly registered.

Sources: src/App.php68 src/App.php99-101

Service Registration Patterns

Services are registered in the container using three distinct patterns depending on their lifecycle and dependencies.

Pattern 1: Singleton Services

The Light\App instance itself is registered as a singleton, along with other framework-level services:

src/App.php74


This ensures that all services receive the same App instance when requesting it as a dependency.

Sources: src/App.php74

Pattern 2: Class-Based Registration

Most controllers are registered by their class name, enabling the container to instantiate them with automatic constructor injection:

src/App.php75-97


When these controllers are resolved, League Container automatically inspects their constructors and injects registered dependencies.

Sources: src/App.php75-97

Pattern 3: Factory-Based Registration

Services requiring complex initialization use factory closures:

src/App.php86-88


This pattern is used when:

  • Constructor arguments cannot be resolved automatically
  • Services need runtime configuration
  • Complex initialization logic is required

Sources: src/App.php86-88

Controller Service Registration

The following table shows all controllers registered in the container during application initialization:

Controller ClassRegistration TypeSpecial Configuration
Controller\AppControllerClass-basedNone
Controller\SystemControllerClass-basedNone
Controller\AuthControllerClass-basedNone
Controller\UserControllerClass-basedNone
Controller\RoleControllerClass-basedNone
Controller\EventLogControllerClass-basedNone
Controller\UserRoleControllerClass-basedNone
Controller\PermissionControllerClass-basedNone
Controller\ConfigControllerClass-basedNone
Controller\UserLogControllerClass-basedNone
Controller\MailLogControllerClass-basedNone
Controller\FileManagerControllerFactoryRequires Drive(0)
Controller\TranslateControllerClass-basedNone
Controller\WebAuthnControllerClass-basedNone
Controller\SystemValueControllerClass-basedNone
Controller\MyFavoriteControllerClass-basedNone
Controller\FileSystemControllerClass-basedNone
Controller\RevisionControllerClass-basedNone
Controller\DatabaseControllerClass-basedNone
Controller\DriveControllerClass-basedNone
Controller\CustomFieldControllerClass-basedNone

Sources: src/App.php75-97

Framework Service Registration

Beyond controllers, several framework-level services are registered for dependency injection:


Sources: src/App.php74 src/App.php103 src/App.php146 src/App.php365

Model Container Integration

The Light\Model base class receives the container via a static method call:

src/App.php103


This allows model classes to access the container when needed, though it's primarily used for internal framework operations rather than general dependency injection.

Sources: src/App.php103

Per-Request Services

During request processing, additional services are registered into the container with request-specific instances.


Sources: src/App.php500-537

Request Object Injection

The current PSR-7 request object is registered to enable controllers to receive it via constructor injection:

src/App.php533


Controllers can now type-hint ServerRequestInterface in their constructors to receive the current request.

Sources: src/App.php533

Auth Service Injection

A fresh Auth\Service instance is created per request and registered in the container:

src/App.php526-534


This service handles JWT token validation and user context. It's also provided to the GraphQL schema factory for authentication and authorization checks on GraphQL operations.

Sources: src/App.php526-534

Dependency Resolution

League Container resolves dependencies automatically through constructor reflection when services are retrieved.

Automatic Constructor Injection

When a controller is resolved from the container, League Container:

  1. Reflects on the controller's constructor
  2. Identifies type-hinted parameters
  3. Resolves each parameter from the container
  4. Instantiates the controller with resolved dependencies

For example, if a controller has this constructor:


The container automatically provides all three dependencies when instantiating the controller.

Sources: composer.lock1555-1635

GraphQLite Integration

The GraphQL system integrates with the container through Light\GraphQL\Server, which receives the container instance:

src/App.php121


GraphQLite uses the container to:

  • Resolve controller instances when executing GraphQL mutations
  • Inject dependencies into GraphQL type classes
  • Provide services to field resolvers

The schema factory obtained from the GraphQL server is configured with authentication services:

src/App.php529-530


Sources: src/App.php121 src/App.php529-530

Container Access

The container can be accessed from the App instance throughout the application lifecycle.

Public Container Getter

The App class provides public access to the container:

src/App.php485-488


This enables custom code to register additional services or resolve dependencies manually when needed.

Sources: src/App.php485-488

Service Retrieval

Services can be retrieved from the container using the PSR-11 interface:


Sources: src/App.php485-488

Dependency Injection Flow

The complete dependency injection flow from application initialization through request processing:


Sources: src/App.php59-147 src/App.php500-537

Best Practices and Patterns

Service Lifetimes

The framework uses different service lifetime patterns:

PatternDescriptionExample
SingletonSingle instance shared across entire applicationApp, Rbac, MountManager
Per-RequestNew instance created for each HTTP requestAuth\Service, ServerRequestInterface
TransientNew instance created each time resolvedControllers (when not cached)

Sources: src/App.php74 src/App.php146 src/App.php365 src/App.php533-534

Constructor Injection Only

The framework exclusively uses constructor injection rather than property or setter injection. This ensures:

  • All dependencies are provided at object creation time
  • Objects are always in a valid state
  • Dependencies are immutable after construction
  • Clear dependency requirements visible in constructor signature

Sources: composer.lock1555-1635

Manual Registration vs Auto-Discovery

Unlike some frameworks that scan directories for services, Light requires explicit registration of all controllers and services. This provides:

  • Explicit control over what services are available
  • Predictable service registration order
  • No performance overhead from directory scanning
  • Clear visibility of all registered services in one location

Sources: src/App.php75-97