3v4l.org

run code in 200+ php & hhvm versions
Bugs & Features
<?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 Joe { public $bob = 'bob'; } class Baz {} $c = new Resolver(new Container); var_dump($c->get(Foo::class)); var_dump($c->get(Baz::class)); var_dump($c->get(Joe::class));
based on YSAG9
Output for 7.1.0 - 7.3.0alpha1
object(Foo)#4 (1) { ["bar"]=> object(Bar)#6 (1) { ["baz"]=> object(Baz)#8 (0) { } } } object(Baz)#8 (0) { } object(Joe)#10 (1) { ["bob"]=> string(3) "bob" }
Output for 7.0.30
Fatal error: Uncaught TypeError: Return value of Container::set() must be an instance of void, none returned in /in/M01FL:23 Stack trace: #0 /in/M01FL(59): Container->set('Baz', Object(Closure)) #1 /in/M01FL(97): Resolver->get('Baz') #2 /in/M01FL(81): Resolver->getArgument('Baz') #3 /in/M01FL(59): Resolver->resolve('Bar') #4 /in/M01FL(97): Resolver->get('Bar') #5 /in/M01FL(81): Resolver->getArgument('Bar') #6 /in/M01FL(59): Resolver->resolve('Foo') #7 /in/M01FL(111): Resolver->get('Foo') #8 {main} thrown in /in/M01FL on line 23
Process exited with code 255.
Output for hhvm-3.22.0
Fatal error: Uncaught Error: Parameter $rules is variadic and has a type constraint (WireRule); variadic params with type constraints are not supported in non-Hack files in /in/M01FL:-1 Stack trace: #0 {main}
Process exited with code 255.
Output for hhvm-3.18.5 - 3.21.3
Fatal error: Uncaught Error: Parameter $rules is variadic and has a type constraint (WireRule); variadic params with type constraints are not supported in non-Hack files in /in/M01FL:50 Stack trace: #0 {main}
Process exited with code 255.
Output for 5.6.30
Parse error: syntax error, unexpected ':', expecting ';' or '{' in /in/M01FL on line 17
Process exited with code 255.