3v4l.org

run code in 300+ PHP versions simultaneously
<?php # basic container class Container { private $raw; // callbacks private $values; // objects private $locked; public function __construct(array $config = []) { foreach($config as $id => $callback){ $this->set($id, $callback); } } public function set(string $id, callable $callback): void { if(isset($this->locked[$id])){ throw new LockedIdException(); } $this->raw[$id] = $callback; } public function get(string $id) { if(!isset($this->raw[$id])){ throw new UnknownIdException(); } if(isset($this->values[$id])){ return $this->values[$id]; } $cb = $this->raw[$id]; $val = $this->values[$id] = $cb($this); $this->locked[$id] = true; return $val; } public function has(string $id): bool { return isset($this->values[$id]); } } class Resolver { public function __construct(Container $container, WireRule ...$rules) { $this->c = $container; $this->rules = $rules; } public function get(string $class) { if(!$this->c->has($class)){ $this->c->set($class, $this->resolve($class)); } return $this->c->get($class); } public function resolve(string $class): callable { if(!class_exists($class)){ throw new UnknownIdException(); } if(!method_exists($class, '__construct')){ return function(Container $c) use ($class){ return new $class; }; } $constructor = new \ReflectionMethod($class, '__construct'); if(count($params = $constructor->getParameters()) === 0){ return function(Container $c) use ($class){ return new $class; }; } foreach($params as $param){ $args[] = $param->hasType() ? $this->getArgument($param->getType()->__toString()) : null; } return function(Container $c) use ($class, $args){ return new $class(...$args); }; } public function getArgument(string $type) { foreach($this->rules as $rule){ if($rule->match($type)){ $type = $rule->getWiredClass($type); } } return $type ? $this->get($type) : null; } } class Foo { public function __construct(Bar $bar){ $this->bar = $bar; }} class Bar { public function __construct(Baz $baz){ $this->baz = $baz; }} class Baz {} $c = new Resolver(new Container); var_dump($c->get(Foo::class));
Output for 8.2.0 - 8.2.20, 8.3.0 - 8.3.8
Deprecated: Creation of dynamic property Resolver::$c is deprecated in /in/orktj on line 52 Deprecated: Creation of dynamic property Resolver::$rules is deprecated in /in/orktj on line 53 Deprecated: Creation of dynamic property Bar::$baz is deprecated in /in/orktj on line 102 Deprecated: Creation of dynamic property Foo::$bar is deprecated in /in/orktj on line 101 object(Foo)#4 (1) { ["bar"]=> object(Bar)#6 (1) { ["baz"]=> object(Baz)#8 (0) { } } }
Output for 7.1.0 - 7.1.33, 7.2.0 - 7.2.33, 7.3.0 - 7.3.33, 8.0.0 - 8.0.30, 8.1.0 - 8.1.29
object(Foo)#4 (1) { ["bar"]=> object(Bar)#6 (1) { ["baz"]=> object(Baz)#8 (0) { } } }
Output for 7.4.0 - 7.4.33
Deprecated: Function ReflectionType::__toString() is deprecated in /in/orktj on line 81 Deprecated: Function ReflectionType::__toString() is deprecated in /in/orktj on line 81 object(Foo)#4 (1) { ["bar"]=> object(Bar)#6 (1) { ["baz"]=> object(Baz)#8 (0) { } } }

preferences:
197.95 ms | 402 KiB | 205 Q