monkeyscloud / monkeyslegion-di
Production-ready PSR-11 container for MonkeysLegion — auto-wiring, attributes, compiled container.
Installs: 482
Dependents: 9
Suggesters: 0
Security: 0
Stars: 0
Watchers: 1
Forks: 0
Open Issues: 0
pkg:composer/monkeyscloud/monkeyslegion-di
Requires
- php: ^8.4
- ext-pcntl: *
- ext-pdo: *
- ext-posix: *
- ext-simplexml: *
- psr/container: ^2.0
This package is auto-updated.
Last update: 2026-02-18 01:39:34 UTC
README
A production-ready PSR-11 dependency injection container for PHP 8.4+ with auto-wiring, PHP attributes, interface binding, and compiled container support.
Installation
composer require monkeyscloud/monkeyslegion-di
Quick Start
use MonkeysLegion\DI\Container; $container = new Container([ LoggerInterface::class => fn() => new FileLogger('/var/log/app.log'), ]); // Auto-wires dependencies automatically $service = $container->get(UserService::class);
Features
Auto-Wiring
The container resolves constructor dependencies automatically by inspecting type hints — no configuration needed for concrete classes:
class UserService { public function __construct( private UserRepository $repo, private LoggerInterface $logger, ) {} } // Just works — both dependencies are resolved recursively $service = $container->get(UserService::class);
Factory Definitions
Register services with factory closures for full control over instantiation:
$container = new Container([ PDO::class => fn() => new PDO('mysql:host=localhost;dbname=app', 'user', 'pass'), CacheInterface::class => fn(ContainerInterface $c) => new RedisCache( $c->get(Redis::class), ), ]);
Runtime Registration
Register or override services at runtime:
$container->set('mailer', fn() => new SmtpMailer($config)); $container->set(LoggerInterface::class, new NullLogger());
Interface Binding
Map abstractions to concrete implementations:
$container->bind(LoggerInterface::class, FileLogger::class); $container->bind(CacheInterface::class, RedisCache::class); // Now any class depending on LoggerInterface gets FileLogger $service = $container->get(UserService::class);
PHP 8.4 Attributes
#[Inject] — Override Parameter Resolution
class NotificationService { public function __construct( #[Inject('slack.logger')] private LoggerInterface $logger, ) {} }
#[Transient] — Fresh Instance Every Time
#[Transient] class RequestContext { public readonly string $id; public function __construct() { $this->id = uniqid('req_', true); } } // Each call returns a new instance $a = $container->get(RequestContext::class); $b = $container->get(RequestContext::class); assert($a !== $b);
#[Singleton] — Explicit Singleton (Default Behavior)
#[Singleton] class DatabaseConnection { // Cached after first resolution (this is the default lifecycle, // but the attribute makes intent explicit) }
#[Tagged] — Service Aggregation
#[Tagged('event.listener')] class UserCreatedListener { /* ... */ } #[Tagged('event.listener')] class AuditLogListener { /* ... */ } // Retrieve all tagged services $listeners = $container->getTagged('event.listener');
Service Tagging (Programmatic)
$container->tag(UserCreatedListener::class, 'event.listener'); $container->tag(AuditLogListener::class, ['event.listener', 'loggable']); $listeners = $container->getTagged('event.listener');
Transient Lifecycle (Programmatic)
$container->transient(RequestContext::class);
Builder Pattern
Use ContainerBuilder for structured setup with providers:
use MonkeysLegion\DI\ContainerBuilder; $builder = new ContainerBuilder(); $builder ->addDefinitions([ PDO::class => fn() => new PDO($dsn, $user, $pass), ]) ->set('app.debug', fn() => true) ->bind(LoggerInterface::class, FileLogger::class) ->tag(UserCreatedListener::class, 'event.listener') ->transient(RequestContext::class); $container = $builder->build();
Compiled Container (Production)
Pre-compile the container for faster boot times in production:
use MonkeysLegion\DI\ContainerBuilder; use MonkeysLegion\DI\ContainerDumper; // Build and dump (deploy step) $builder = new ContainerBuilder(); $builder->addDefinitions([/* ... */]); $container = $builder->build(); $dumper = new ContainerDumper(); $dumper->dump($container, '/var/cache/compiled_container.php'); // Load in production (fast boot) $builder = new ContainerBuilder(); $builder ->addDefinitions([/* same definitions */]) ->enableCompilation('/var/cache'); $container = $builder->build(); // Returns CompiledContainer if cache exists
Testing Support
// Reset cached instances between tests $container->reset();
API Reference
Container
| Method | Description |
|---|---|
get(string $id): mixed |
Resolve a service (PSR-11) |
has(string $id): bool |
Check if service exists (PSR-11) |
set(string $id, callable|object $def): void |
Register/override at runtime |
bind(string $abstract, string $concrete): void |
Map interface → implementation |
tag(string $id, string|array $tags): void |
Tag a service |
getTagged(string $tag): array |
Get all services with a tag |
transient(string $id): void |
Mark as non-singleton |
reset(): void |
Clear cached instances |
getDefinitions(): array |
Get registered definitions |
ContainerBuilder
| Method | Description |
|---|---|
addDefinitions(array $defs): self |
Merge definitions (won't overwrite) |
set(string $id, callable|object $def): self |
Register single definition |
bind(string $abstract, string $concrete): self |
Map interface → implementation |
tag(string $id, string|array $tags): self |
Tag a service |
transient(string $id): self |
Mark as non-singleton |
enableCompilation(string $dir): self |
Enable compiled container |
build(): Container |
Build the container |
Attributes
| Attribute | Target | Description |
|---|---|---|
#[Inject('id')] |
Parameter | Override auto-wired parameter |
#[Singleton] |
Class | Explicit singleton (default) |
#[Transient] |
Class | New instance per get() |
#[Tagged('tag')] |
Class | Auto-register tag (repeatable) |
Error Handling
The container throws PSR-11 compliant exceptions:
ServiceNotFoundException— service ID not found (Psr\Container\NotFoundExceptionInterface)ServiceResolveException— circular dependency or unresolvable parameter (Psr\Container\ContainerExceptionInterface)
Requirements
- PHP 8.4+
psr/container ^2.0
Testing
composer install vendor/bin/phpunit --testdox
License
MIT