/** * For classes that expect dependencies in their constructor, you can use * this method instead of "new" with lots of Container::get calls. * * Type-hinted arguments _must_ match a dependency. If no dependency exists, * a new instance will be passed. * * @return mixed An object of the same class as called on, with dependencies * injected through its constructor. * @throws Disclosure\TypeMismatchException if the retrieved dependency does * not satisfy the argument's type hint. * @throws Psr\Container\Exception\NotFoundExceptionInterface if _any_ of * the requested dependencies could not be resolved. */ public static function resolve() { $reflection = new ReflectionClass(__CLASS__); $constructor = $reflection->getConstructor(); $args = []; $container = new Container(); foreach ($constructor->getParameters() as $parameter) { $name = $parameter->name; $e = $inject = $class = null; try { $inject = $container->get($name); } catch (NotFoundExceptionInterface $e) { } if ($class = $parameter->getClass()) { $instance = $class->getName(); if (isset($inject)) { if ($inject instanceof $instance) { $args[] = $inject; continue; } else { throw new TypeMismatchException(get_class($inject)); } } if ($class->implementsInterface('Disclosure\\Injectable')) { $args[] = $class::resolve(); } else { $args[] = $class->newInstance(); } } elseif ($parameter->isDefaultValueAvailable()) { $args[] = $parameter->getDefaultValue(); } elseif (isset($e)) { throw $e; } elseif (isset($inject)) { $args[] = $inject; } } return $reflection->newInstanceArgs($args); }
<?php namespace Disclosure\Test; use Disclosure\Injector; use Disclosure\NotFoundException; use Demo; use Gentry\Property; use Gentry\Group; use Disclosure\Container; $container = new Container(); $container->register(function (&$foo, &$bar, &$baz) { $foo = new Demo\BasicInjection1(); $bar = new Demo\BasicInjection2(); $baz = new Demo\BasicInjection3(); }); $container->register(function (&$fizz) { $fizz = new Demo\DeepInjection(); }); /** * Injector should inject requested classes */ class InjectorTest { /** * {0}::$foo is a BasicInjection1 */ public function fooIsSet(Demo\Basic $foo) { (yield new Demo\BasicInjection1()); }