georgeff/container

A lightweight dependency injection container implementing PSR-11

Maintainers

Package info

github.com/MikeGeorgeff/container

pkg:composer/georgeff/container

Statistics

Installs: 583

Dependents: 1

Suggesters: 0

Stars: 0

Open Issues: 0

1.1.0 2026-06-20 01:46 UTC

This package is auto-updated.

Last update: 2026-06-20 01:49:37 UTC


README

A lightweight dependency injection container implementing PSR-11.

Installation

composer require georgeff/container

Usage

Registering Definitions

Register a definition by providing an ID and a callable factory. The container instance is passed to the factory.

use Georgeff\Container\Container;

$container = new Container();

$container->add('database', function (Container $container) {
    return new DatabaseConnection('localhost', 'mydb');
});

Shared Definitions

Shared definitions are resolved once and the same instance is returned on subsequent calls.

$container->addShared('database', function (Container $container) {
    return new DatabaseConnection('localhost', 'mydb');
});

// Or pass true as the third argument to add()
$container->add('database', function (Container $container) {
    return new DatabaseConnection('localhost', 'mydb');
}, true);

Resolving Definitions

$db = $container->get('database');

Aliases

Aliases allow you to resolve a definition by an alternate name, useful for binding interfaces to implementations.

$container->addShared(DatabaseConnection::class, function (Container $container) {
    return new DatabaseConnection('localhost', 'mydb');
});

$container->addAlias(DatabaseConnection::class, ConnectionInterface::class);

// Resolves the DatabaseConnection definition
$db = $container->get(ConnectionInterface::class);

Resolution Hooks

Hooks allow you to observe or react to service resolution. Four hooks are available: global pre, service-specific pre, service-specific post, and global post. When multiple hooks are registered they fire in that order — global pre first, global post last.

Global pre-resolution — fires on every get() call, including cache hits for shared services:

$container->onResolving(function (string $id): void {
    echo "Resolving: $id";
});

Service-specific pre-resolution — fires only when the given ID is resolved:

$container->onResolvingId('database', function (string $id): void {
    echo "Resolving database";
});

Service-specific post-resolution — fires after the factory runs for the given ID; does not fire on cache hits:

$container->afterResolvedId('database', function (string $id, mixed $instance): void {
    echo "Resolved database";
});

Global post-resolution — fires after the factory runs for any service; does not fire on cache hits:

$container->afterResolved(function (string $id, mixed $instance): void {
    echo "Resolved: $id";
});

All hooks receive the canonical ID after alias resolution, not the alias used to call get(). Multiple hooks of the same type can be registered and all will fire in registration order.

Checking for Definitions

$container->has('database');    // true
$container->has('nonexistent'); // false

Exceptions

  • DefinitionNotFoundException — thrown when getting a definition that does not exist or aliasing a non-existing definition. Implements PSR-11 NotFoundExceptionInterface.
  • CircularDependencyException — thrown when a circular dependency is detected during resolution. Implements PSR-11 ContainerExceptionInterface.
  • ContainerException — thrown when an error occurs during definition resolution. Implements PSR-11 ContainerExceptionInterface.

License

MIT