diff --git a/README.md b/README.md index 222b7ec..5f1a329 100644 --- a/README.md +++ b/README.md @@ -26,6 +26,8 @@ into arbitrary code. - ConsumerInitializer = ClassName | Consumer - ServiceInitializer = ConsumerInitializer | Value +Construction +------------ Container is initialized with raw values, no Initalizers allowed: ```php @@ -40,6 +42,8 @@ You can set a name which will be used to refer to container itself: $container = new SD\DependencyInjection\Container([], 'container'); ``` +Registering services +-------------------- Services are registered with ServiceInitializers: ```php @@ -62,6 +66,19 @@ $container->register('helloWorld', function ($name) { $container->register('name', $container->value('Skywalker')); ``` +You can extend registered services: + +```php +$container->register('currency', SD\Currency\Repository::class); +$container->extend('currency', function ($container, $currency) { + $store = $container->produce(SD\CurrencyStore\Wpdb::class); + $currency->setStore($store); + return $currency; +}); +``` + +Consumer production +------------------- Consumers are produced with ConsumerInitializers (Value is not supported): ```php diff --git a/src/Container.php b/src/Container.php index b1e87d0..678d2e2 100644 --- a/src/Container.php +++ b/src/Container.php @@ -21,6 +21,20 @@ public function register($name, $initializer) { } } + public function extend($name, $extender) { + if (isset($this->services[$name])) { + $this->services[$name] = $this->produce($extender); + } elseif (isset($this->initializers[$name])) { + $initializer = $this->initializers[$name]; + $this->initializers[$name] = function () use ($extender, $initializer, $name) { + $this->services[$name] = $this->produce($initializer); + return $this->inject($extender); + }; + } else { + throw new Exception("Cannot extend unknown service $name"); + } + } + public function value($value) { return new Value($value); } diff --git a/tests/ContainerTest.php b/tests/ContainerTest.php index 79558a6..c2bb2df 100644 --- a/tests/ContainerTest.php +++ b/tests/ContainerTest.php @@ -14,7 +14,7 @@ public function testRegisterClassName() { ], 'container' ); - $serviceName = 'hello_world'; + $serviceName = 'helloWorld'; $className = HelloWorldService::class; $container->register($serviceName, $className); $service = $container->get($serviceName); @@ -30,4 +30,23 @@ public function testDetectCyclicDependencies() { $this->expectException(Exception::class); $container->get('a'); } + + public function testExtend() { + $name1 = 'Jar Jar Binks'; + $name2 = 'Palpatine'; + $container = new Container( + [ + 'name' => $name1, + ], + 'container' + ); + $serviceName = 'helloWorld'; + $container->register($serviceName, HelloWorldService::class); + $container->extend($serviceName, function ($helloWorld) use ($name2) { + $helloWorld->setName($name2); + return $helloWorld; + }); + $service = $container->get($serviceName); + $this->assertEquals($name2, $service->getName(), 'Must return modified name'); + } } diff --git a/tests/HelloWorldService.php b/tests/HelloWorldService.php index 9e03868..1d76ef3 100644 --- a/tests/HelloWorldService.php +++ b/tests/HelloWorldService.php @@ -9,7 +9,7 @@ class HelloWorldService implements DeclarerInterface { private $name; - public function __construct($name) { + public function __construct(string $name) { $this->name = $name; } @@ -17,7 +17,11 @@ public function declareDependencies() { return ['container']; } - public function getName() { + public function setName(string $name) { + $this->name = $name; + } + + public function getName(): string { return $this->name; }