lighthouse/container

PSR-11 Dependency Injection Container for the Lighthouse framework

Installs: 11

Dependents: 1

Suggesters: 0

Security: 0

Stars: 0

Watchers: 0

Forks: 0

Open Issues: 0

pkg:composer/lighthouse/container

v0.1.0 2025-12-17 13:40 UTC

This package is auto-updated.

Last update: 2025-12-17 18:27:02 UTC


README

A PSR-11 compliant Dependency Injection Container for the Lighthouse framework.

Installation

composer require lighthouse/container

Requirements

  • PHP 8.2 or higher

Features

  • Full PSR-11 compliance
  • Autowiring via reflection
  • Manual bindings
  • Singletons
  • Factories
  • Interface to implementation binding
  • Method injection
  • Circular dependency detection

Quick Start

Basic Autowiring

The container can automatically resolve class dependencies:

use Lighthouse\Container\Container;

class Logger
{
    public function log(string $message): void
    {
        echo $message;
    }
}

class UserService
{
    public function __construct(
        private Logger $logger
    ) {}
}

$container = new Container();

// Automatically resolves Logger dependency
$userService = $container->get(UserService::class);

Manual Bindings

Bind interfaces to implementations:

interface CacheInterface
{
    public function get(string $key): mixed;
}

class RedisCache implements CacheInterface
{
    public function get(string $key): mixed
    {
        // Redis implementation
    }
}

$container->bind(CacheInterface::class, RedisCache::class);

$cache = $container->get(CacheInterface::class);
// Returns instance of RedisCache

Closure Bindings

Use closures for complex instantiation:

$container->bind(Database::class, function (Container $c) {
    $config = $c->get(Config::class);
    
    return new Database(
        host: $config->get('db.host'),
        user: $config->get('db.user'),
        pass: $config->get('db.pass')
    );
});

Singletons

Register a binding that returns the same instance:

$container->singleton(Database::class, function (Container $c) {
    return new Database(/* ... */);
});

$db1 = $container->get(Database::class);
$db2 = $container->get(Database::class);

// $db1 === $db2 (same instance)

Register Existing Instance

$logger = new Logger();
$container->instance(Logger::class, $logger);

// Always returns the same $logger instance

Factories

Register a factory that creates a new instance each time:

$container->factory(RequestId::class, function () {
    return new RequestId(uniqid());
});

$id1 = $container->get(RequestId::class); // RequestId with unique id
$id2 = $container->get(RequestId::class); // Different RequestId

Method Injection

Call methods with automatic dependency resolution:

class OrderController
{
    public function store(OrderService $service, Validator $validator): Order
    {
        // ...
    }
}

$controller = new OrderController();

// Automatically resolves OrderService and Validator
$result = $container->call($controller, 'store');

// With additional parameters
$result = $container->call($controller, 'update', ['id' => 123]);

PSR-11 Methods

// Check if entry exists
$container->has(Logger::class); // true/false

// Get entry (throws NotFoundException if not found)
$container->get(Logger::class);

Error Handling

The container throws PSR-11 compliant exceptions:

use Lighthouse\Container\Exception\NotFoundException;
use Lighthouse\Container\Exception\ContainerException;

try {
    $container->get('UnknownClass');
} catch (NotFoundException $e) {
    // Entry not found
} catch (ContainerException $e) {
    // Error during resolution (circular dependency, etc.)
}

Circular Dependency Detection

The container detects circular dependencies and throws a clear error:

class A {
    public function __construct(B $b) {}
}

class B {
    public function __construct(A $a) {}
}

$container->get(A::class);
// Throws: ContainerException: Circular dependency detected while resolving "A"

API Reference

Method Description
get(string $id) Resolve an entry (PSR-11)
has(string $id) Check if entry exists (PSR-11)
bind(string $id, mixed $concrete) Register a binding
singleton(string $id, mixed $concrete) Register a shared binding
instance(string $id, mixed $instance) Register an existing instance
factory(string $id, callable $factory) Register a factory
call(object|string $target, string $method, array $params) Call method with DI
flush() Clear all bindings and instances
getBindings() Get all registered binding IDs
isShared(string $id) Check if binding is a singleton

Testing

composer test

License

MIT License. See LICENSE for details.

Part of the Lighthouse Framework

This package is part of the Lighthouse Framework, an educational PHP framework designed to teach how modern frameworks work internally.