Skip to content

Commit

Permalink
Add optional references (#43)
Browse files Browse the repository at this point in the history
  • Loading branch information
vjik committed Oct 25, 2022
1 parent 3fcebf6 commit 69a5935
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 13 deletions.
15 changes: 8 additions & 7 deletions CHANGELOG.md
Expand Up @@ -2,24 +2,25 @@

## 2.0.1 under development

- no changes in this release.
- Enh #43: Add `Reference::optional()` method that returns `null` when there is no dependency defined
in container (@vjik)

## 2.0.0 June 17, 2022

- New #37: Make method `DefinitionValidator::validateArrayDefinition()` public (vjik)
- New #37: Make method `DefinitionValidator::validateArrayDefinition()` public (@vjik)
- Chg #30: Rename method `ArrayDefinition::setReferenceContainer()` to `withReferenceContainer()` and make it
immutable (vjik)
- Chg #37: Remove method `ParameterDefinition::isBuiltin()` (vjik)
immutable (@vjik)
- Chg #37: Remove method `ParameterDefinition::isBuiltin()` (@vjik)

## 1.0.2 April 01, 2022

- Bug #32: Throw exception instead of returning default value if optional dependency exists but there is an exception
when getting it (vjik)
- Bug #34: In one of edge cases don't throw exception if container returned result of incorrect type (vjik)
when getting it (@vjik)
- Bug #34: In one of edge cases don't throw exception if container returned result of incorrect type (@vjik)

## 1.0.1 December 19, 2021

- Bug #31: Add support for objects as default parameter values (vjik)
- Bug #31: Add support for objects as default parameter values (@vjik)

## 1.0.0 November 30, 2021

Expand Down
14 changes: 14 additions & 0 deletions README.md
Expand Up @@ -144,6 +144,20 @@ dependencies:
]
```

Optional reference returns `null` when there's no corresponding definition in container:

```php
[
MyService::class => [
'__construct()' => [
// If container doesn't have definition for `EventDispatcherInterface` reference returns `null`
// when resolving dependencies
Reference::optional(EventDispatcherInterface::class),
],
],
]
```

The `DynamicReference` defines a dependency to a service not defined in the container:

```php
Expand Down
31 changes: 25 additions & 6 deletions src/Reference.php
Expand Up @@ -29,26 +29,45 @@
final class Reference implements ReferenceInterface
{
private string $id;
private bool $optional;

private function __construct(string $id)
/**
* @param mixed $id
*
* @throws InvalidConfigException
*/
private function __construct($id, bool $optional)
{
if (!is_string($id)) {
throw new InvalidConfigException('Reference ID must be string.');
}

$this->id = $id;
$this->optional = $optional;
}

/**
* @throws InvalidConfigException If ID is not string.
*/
public static function to($id): self
{
if (!is_string($id)) {
throw new InvalidConfigException('Reference ID must be string.');
}
return new self($id, false);
}

return new self($id);
/**
* Optional reference returns `null` when there is no corresponding definition in container.
*
* @param mixed $id ID of the service or object to point to.
*
* @throws InvalidConfigException If ID is not string.
*/
public static function optional($id): self
{
return new self($id, true);
}

public function resolve(ContainerInterface $container)
{
return $container->get($this->id);
return (!$this->optional || $container->has($this->id)) ? $container->get($this->id) : null;
}
}
11 changes: 11 additions & 0 deletions tests/Unit/ReferenceTest.php
Expand Up @@ -7,7 +7,9 @@
use PHPUnit\Framework\TestCase;
use Yiisoft\Definitions\Exception\InvalidConfigException;
use Yiisoft\Definitions\Reference;
use Yiisoft\Definitions\Tests\Support\Car;
use Yiisoft\Definitions\Tests\Support\EngineInterface;
use Yiisoft\Test\Support\Container\SimpleContainer;

final class ReferenceTest extends TestCase
{
Expand All @@ -16,4 +18,13 @@ public function testInvalid(): void
$this->expectException(InvalidConfigException::class);
Reference::to(['class' => EngineInterface::class]);
}

public function testOptional(): void
{
$container = new SimpleContainer();

$reference = Reference::optional(Car::class);

$this->assertNull($reference->resolve($container));
}
}

0 comments on commit 69a5935

Please sign in to comment.