Properly implement the router with config and interfaces
Expand the container with aliases and argument autowiring
This commit is contained in:
@ -3,19 +3,20 @@
|
||||
namespace Ardent\Undercurrent\Container;
|
||||
|
||||
use Exception;
|
||||
use ReflectionClass;
|
||||
|
||||
class GenericContainer
|
||||
class GenericContainer implements ContainerInterface
|
||||
{
|
||||
private array $definitions = [];
|
||||
|
||||
private array $instances = [];
|
||||
|
||||
private array $aliases = [];
|
||||
|
||||
public function add(string $className, ?callable $definition = null, bool $singleton = true): self
|
||||
{
|
||||
if (!$definition) {
|
||||
$definition = function () use ($className) {
|
||||
return new $className();
|
||||
};
|
||||
$definition = fn() => $this->autowire($className);
|
||||
}
|
||||
|
||||
$this->definitions[$className] = [
|
||||
@ -26,29 +27,57 @@ class GenericContainer
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function alias(string $alias, string $className): self
|
||||
{
|
||||
$this->aliases[$alias] = $className;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @template TClassName
|
||||
* @param class-string<TClassName> $className
|
||||
* @return TClassName
|
||||
* @throws Exception
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function get(string $className): object
|
||||
{
|
||||
if (isset($this->aliases[$className])) {
|
||||
$className = $this->aliases[$className];
|
||||
}
|
||||
if (!isset($this->definitions[$className])) {
|
||||
throw new Exception("Class $className not found in container");
|
||||
}
|
||||
|
||||
$definition = $this->definitions[$className]['definition'];
|
||||
|
||||
if ($this->definitions[$className]['singleton']) {
|
||||
if (isset($this->instances[$className])) {
|
||||
return $this->instances[$className];
|
||||
}
|
||||
$instance = $definition();
|
||||
$instance = $definition($this);
|
||||
$this->instances[$className] = $instance;
|
||||
} else {
|
||||
$instance = $definition();
|
||||
$instance = $definition($this);
|
||||
}
|
||||
|
||||
return $instance;
|
||||
}
|
||||
|
||||
private function autowire(string $className): ?object
|
||||
{
|
||||
$reflection = new ReflectionClass($className);
|
||||
$constructor = $reflection->getConstructor();
|
||||
if (!$constructor) {
|
||||
return new $className();
|
||||
}
|
||||
|
||||
$params = [];
|
||||
foreach ($constructor->getParameters() as $parameter) {
|
||||
$type = $parameter->getType();
|
||||
if (!$type) {
|
||||
throw new Exception("Parameter {$parameter->getName()} in $className has no type");
|
||||
}
|
||||
$params[] = $this->get($type->getName());
|
||||
}
|
||||
|
||||
return new $className(...$params);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user