Created
April 3, 2025 21:56
-
-
Save audinue/5c66a31b455d50a2ee5cea449fe58ff5 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
class Container | |
{ | |
/** | |
* @var array<string, mixed> | |
*/ | |
private $values; | |
/** | |
* @var array<string, callable(Container $container): mixed> | |
*/ | |
private $moduleFactories; | |
/** | |
* @var array<string, mixed> | |
*/ | |
private $moduleCache; | |
/** | |
* @var array<string, callable(Container $container, mixed ...$args): mixed> | |
*/ | |
private $objectFactories; | |
/** | |
* @var array<string, callable(Container $container, mixed ...$args): mixed> | |
*/ | |
private $objectFactoryCache; | |
/** | |
* @param string $key | |
* @return mixed | |
* @throws \Exception When the value is undefined. | |
*/ | |
function getValue($key) | |
{ | |
if (!isset($this->values[$key])) { | |
throw new \Exception("Undefined value for $key"); | |
} | |
return $this->values[$key]; | |
} | |
/** | |
* @param string $key | |
* @param mixed $value | |
* @return self | |
*/ | |
function setValue($key, $value) | |
{ | |
$this->values[$key] = $value; | |
return $this; | |
} | |
/** | |
* @template T | |
* @param class-string<T> $key | |
* @return callable(Container $container): T | |
* @throws \Exception When the module factory is undefined. | |
*/ | |
function getModuleFactory($key) | |
{ | |
foreach ($this->moduleFactories as $moduleFactoryKey => $moduleFactory) { | |
if (is_a($moduleFactoryKey, $key, true)) { | |
return $moduleFactory; | |
} | |
} | |
throw new \Exception("Undefined module factory for $key"); | |
} | |
/** | |
* @template T | |
* @param class-string<T> $key | |
* @param callable(Container $container): T $moduleFactory | |
* @return self | |
*/ | |
function setModuleFactory($key, $moduleFactory) | |
{ | |
$this->moduleFactories[$key] = $moduleFactory; | |
return $this; | |
} | |
/** | |
* @template T | |
* @param class-string<T> $key | |
* @return callable(Container $container, mixed ...$args): T | |
* @throws \Exception When the object factory is undefined. | |
*/ | |
function getObjectFactory($key) | |
{ | |
foreach ($this->objectFactories as $objectFactoryKey => $objectFactory) { | |
if (is_a($objectFactoryKey, $key, true)) { | |
return $objectFactory; | |
} | |
} | |
throw new \Exception("Undefined object factory for $key"); | |
} | |
/** | |
* @template T | |
* @param class-string<T> $key | |
* @param callable(Container $container, mixed ...$args): T $objectFactory | |
* @return self | |
*/ | |
function setObjectFactory($key, $objectFactory) | |
{ | |
$this->objectFactories[$key] = $objectFactory; | |
return $this; | |
} | |
/** | |
* @template T | |
* @param class-string<T> $key | |
* @return T | |
* @throws \Exception When the module factory is undefined. | |
*/ | |
function getModule($key) | |
{ | |
$module = $this->moduleCache[$key] ?? null; | |
if ($module == null) { | |
$moduleFactory = $this->getModuleFactory($key); | |
$module = $moduleFactory($this); | |
$this->moduleCache[$key] = $module; | |
} | |
return $module; | |
} | |
/** | |
* @template T | |
* @param class-string<T> $key | |
* @param mixed... $args | |
* @return T | |
* @throws \Exception When the object factory is undefined. | |
*/ | |
function createObject($key, ...$args) | |
{ | |
$objectFactory = $this->objectFactoryCache[$key] ?? null; | |
if ($objectFactory == null) { | |
$objectFactory = $this->getObjectFactory($key); | |
$this->objectFactoryCache[$key] = $objectFactory; | |
} | |
return $objectFactory($this, ...$args); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment