Provides an extensible Dependency Injection Service Container for Automated Object Composition, Interception, and Lifetime Management.
You can install the package via composer:
composer require ghostwriter/containerRegistering a service on the given container.
final readonly class Service
{
public function __construct(
private Dependency $dependency
) {}
public function dependency():Dependency
{
return $this->dependency;
}
}
$container = Container::getInstance();
$service = $container->get(Service::class);
assert($service instanceof Service); // true
assert($service->dependency() instanceof Dependency); // trueAutomatically register a service definition class using Composer's extra config in your composer.json file.
Important
A service definition class MUST implement Ghostwriter\Container\Interface\Service\DefinitionInterface [class].
It should look like the following:
{
"extra": {
"ghostwriter": {
"container": {
"definition": "App\\Service\\Definition"
}
}
}
}Registering a service definition on the container.
interface TaskInterface {}
interface TaskCollectionInterface {
public function add(TaskInterface $task): void;
public function count(): int;
}
final readonly class MainTask implements TaskInterface {
public function __construct(
private string $name
) {}
}
final readonly class FirstTask implements TaskInterface {
public function __construct(
private string $name
) {}
}
final class TaskCollection implements TaskCollectionInterface
{
private array $tasks = [];
public function add(TaskInterface $task): void
{
$this->tasks[] = $task;
}
public function count(): int
{
return count($this->tasks);
}
}
final class TaskCollectionFactory implements FactoryInterface
{
public function __invoke(ContainerInterface $container): TaskCollection
{
return new TaskCollection();
}
}
final class TaskCollectionExtension implements ExtensionInterface
{
/** @param TaskCollection $service */
public function __invoke(ContainerInterface $container, object $service): void
{
$service->add(new FirstTask('Task 1'));
$mainTask = $container->build(TaskInterface::class, ['name' => 'Main Task']);
assert($mainTask instanceof MainTask); // true
$service->add($mainTask);
}
}
final readonly class TasksServiceDefinition implements DefinitionInterface
{
public function __invoke(ContainerInterface $container)
{
$container->alias(MainTask::class, TaskInterface::class);
$container->alias(TaskCollection::class, TaskCollectionInterface::class);
$container->extend(TaskCollection::class, TaskCollectionExtension::class);
$container->factory(TaskCollection::class, TaskCollectionFactory::class);
}
}
$container = Container::getInstance();
$container->define(TasksDefinition::class);
$service = $container->get(TaskCollectionInterface::class);
assert($service instanceof TaskCollection); // true
assert($service->count() === 2); // trueRegistering a Contextual Bindings on the container.
interface ClientInterface {}
final readonly class RestClient implements ClientInterface {}
final readonly class GraphQLClient implements ClientInterface {}
final readonly class GitHub
{
public function __construct(
private ClientInterface $client
) {
}
public function getClient(): ClientInterface
{
return $this->client;
}
}
// When GitHub::class asks for ClientInterface::class, it would receive an instance of GraphQLClient::class.
$container->bind(GitHub::class, ClientInterface::class, GraphQLClient::class);
// When any other service asks for ClientInterface::class, it would receive an instance of RestClient::class.
$container->alias(ClientInterface::class, RestClient::class);Registering a service extension on the container.
/**
* @implements ExtensionInterface<GitHubClient>
*/
final readonly class GitHubExtension implements ExtensionInterface
{
/**
* @param GitHubClient $service
*/
public function __invoke(ContainerInterface $container, object $service): void
{
$service->setEnterpriseUrl(
$container->get(GitHubClient::GITHUB_HOST)
);
}
}
$container->alias(GitHubClientInterface::class, GitHubClient::class);
$container->extend(GitHubClientInterface::class, GitHubExtention::class);Registering a service factory on the container.
final readonly class Dependency {}
final readonly class Service
{
public function __construct(
private Dependency $dependency
){}
public function dependency():Dependency
{
return $this->dependency;
}
}
final readonly class ServiceFactory {
public function __invoke(Container $container): Service
{
return new Service($container->get(Dependency::class));
}
}
$container = Container::getInstance();
$container->factory(Service::class, ServiceFactory::class);
$service = $container->get(Service::class);
assert($service instanceof Service); // true
assert($service->dependency() instanceof Dependency); // truecomposer testPlease see CHANGELOG.md for more information what has changed recently.
If you discover any security related issues, please email nathanael.esayeas@protonmail.com instead of using the issue tracker.
The BSD-4-Clause. Please see License File for more information.