Skip to content

Instantly share code, notes, and snippets.

@nikolaposa
Last active March 5, 2019 10:38
Show Gist options
  • Save nikolaposa/811c9e23a77d9daa66cd0a91fd8fcc20 to your computer and use it in GitHub Desktop.
Save nikolaposa/811c9e23a77d9daa66cd0a91fd8fcc20 to your computer and use it in GitHub Desktop.
Hand-writen DI Container
<?php
namespace My;
return [
'dependencies' => [
//Domain
TodoRepository::class => TodoRepositoryFactory::class,
UserRepository::class => UserRepositoryFactory::class,
//Infrastructure
EventStore::class => EventStoreFactory::class,
EventBus::class => EventBusFactory::class,
CommandBus::class => CommandBusFactory::class,
QueryBus::class => QueryBusFactory::class,
ProjectionManager::class => ProjectionManagerFactory::class,
'db.connection.default' => [DbConnectionFactory::class, 'db'],
'db.connection.read' => [DbConnectionFactory::class, 'db'],
MailSender::class => MailSenderFactory::class,
],
];
<?php
declare(strict_types=1);
namespace My;
use Psr\Container\ContainerInterface;
final class Dependencies implements ContainerInterface
{
/** @var ArrayObject */
private $config;
/** @var array */
private $factories;
/** @var object[] */
private $shared = [];
public function __construct(ArrayObject $config)
{
$this->config = $config;
$this->factories = $config['dependencies'];
$this->factories['config'] = function () {
return $this->config;
};
}
public function get($id)
{
$factory = $this->getFactory($id);
if (null === $factory) {
throw DependencyNotFound::forId($id);
}
if ($this->shouldShare($id)) {
return $this->share($id, $factory);
}
return $factory($this, $id);
}
public function has($id): bool
{
return isset($this->factories[$id]);
}
public function config(): ArrayObject
{
return $this->config;
}
public function todoRepository(): TodoRepository
{
return $this->get(TodoRepository::class);
}
public function userRepository(): UserRepository
{
return $this->get(UserRepository::class);
}
private function getFactory(string $id): ?callable
{
if (! isset($this->factories[$id])) {
return null;
}
if (\is_string($this->factories[$id])) {
$factoryClass = $this->factories[$id];
$factory = new $factoryClass();
$this->factories[$id] = $factory;
}
return $this->factories[$id];
}
private function shouldShare(string $id): bool
{
return !isset($this->config['shared_dependencies'][$id]) || true === $this->config['shared_dependencies'][$id];
}
private function share(string $key, callable $factory)
{
if (!array_key_exists($key, $this->shared)) {
$this->shared[$key] = $factory($this, $key);
}
return $this->shared[$key];
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment