Last active
July 29, 2022 17:25
-
-
Save missoxd/51022026929a2a6c9d109727622804fa to your computer and use it in GitHub Desktop.
This file contains 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 | |
{ | |
private array $instances = []; | |
public function set(string $key, $value): void | |
{ | |
if (is_string($value) || is_callable($value)) { | |
$value = $this->resolve($value); | |
} | |
$this->instances[$key] = $value; | |
} | |
public function get(string $id) | |
{ | |
if ($this->has($id)) { | |
return $this->instances[$id]; | |
} | |
try { | |
return $this->instances[$id] = $this->resolve($id); | |
} catch (ReflectionException $ex) { | |
throw new Exception($ex->getMessage()); | |
} catch (Exception $ex) { | |
throw new Exception($ex->getMessage()); | |
} | |
} | |
public function has(string $id): bool | |
{ | |
return isset($this->instances[$id]); | |
} | |
private function resolve($id) | |
{ | |
if (is_callable($id)) { | |
return $id(); | |
} | |
return $this->instance(new ReflectionClass($id)); | |
} | |
private function instance(ReflectionClass $class) | |
{ | |
$constructor = $class->getConstructor(); | |
if (is_null($constructor) || $constructor->getNumberOfRequiredParameters() === 0) { | |
return $class->newInstance(); | |
} | |
$args = array_reduce($constructor->getParameters(), fn(array $carry, $arg) => (($type = $arg->getType()) ? $carry + [$this->get($type->getName())] : $carry), []); | |
return $class->newInstanceArgs($args); | |
} | |
} | |
class Test1 { | |
public string $name = 'Default Test 1 Name'; | |
} | |
class Test2 | |
{ | |
public string $name = 'Default Test 2 Name'; | |
public function __construct( | |
private Test1 $test1 | |
) {} | |
} | |
class Test3 | |
{ | |
public string $name = 'Default Test 3 Name'; | |
public function __construct( | |
private Test2 $test2 | |
) {} | |
} | |
$customTest1 = new Test1; | |
$customTest1->name = 'Custom Test 1 Name'; | |
$ioc = new Container; | |
$ioc->set(Test1::class, $customTest1); | |
var_dump($ioc->get(Test3::class)); | |
/* | |
PHP 8.1.x | |
Output: | |
object(Test3)#6 (2) { | |
["name"]=> | |
string(19) "Default Test 3 Name" | |
["test2":"Test3":private]=> | |
object(Test2)#11 (2) { | |
["name"]=> | |
string(19) "Default Test 2 Name" | |
["test1":"Test2":private]=> | |
object(Test1)#1 (1) { | |
["name"]=> | |
string(18) "Custom Test 1 Name" | |
} | |
} | |
} | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment