Skip to content

Commit

Permalink
Option to don't share a service, always new instance is created
Browse files Browse the repository at this point in the history
  • Loading branch information
ElGigi committed Nov 24, 2022
1 parent e07c3e5 commit 07489f3
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 22 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).

## [2.2.0] - 2022-11-24

### Added

- Option to don't share a service, always new instance is created

## [2.1.1] - 2021-11-10

### Changed
Expand Down
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,18 @@ $container->addService($service);

> Constructor of Service object.
- `Service::setNullable(bool $nullable = true): Service`

> Service can be null after factory execution (false by default).
- `Service::setShared(bool $shared = true): Service`

> Share a service, always same instance returned for a shared service.
- `Service::addProvide(string ...$provide): Service`

> Add provided class/interfaces/alias by service.
- `Service::addArgument(string $name, mixed $value): Service`

> Add argument to make an instance of service class.
Expand Down
69 changes: 47 additions & 22 deletions src/Service/Service.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ class Service
{
protected string $class;
protected bool $nullable = false;
protected bool $shared = true;
protected array $provides = [];
protected mixed $factory = null;
protected array $arguments = [];
Expand Down Expand Up @@ -65,6 +66,7 @@ public function __serialize(): array
return [
'class' => $this->class,
'nullable' => $this->nullable,
'shared' => $this->shared,
'factory' => $this->factory,
'alias' => $this->alias,
'arguments' => $this->arguments,
Expand All @@ -83,6 +85,7 @@ public function __unserialize(array $data): void
{
$this->class = $data['class'] ?? throw new ContainerException('Serialization error');
$this->nullable = $data['nullable'] ?? throw new ContainerException('Serialization error');
$this->shared = $data['shared'] ?? true;
$this->factory = $data['factory'] ?? throw new ContainerException('Serialization error');
$this->alias = $data['alias'] ?? throw new ContainerException('Serialization error');
$this->arguments = $data['arguments'] ?? throw new ContainerException('Serialization error');
Expand Down Expand Up @@ -123,6 +126,30 @@ public function setNullable(bool $nullable = true): static
return $this;
}

/**
* Is shared?
*
* @return bool
*/
public function isShared(): bool
{
return $this->shared ?? false;
}

/**
* Set shared.
*
* @param bool $shared
*
* @return static
*/
public function setShared(bool $shared = true): static
{
$this->shared = $shared;

return $this;
}

/**
* Get alias.
*
Expand Down Expand Up @@ -272,13 +299,16 @@ public function get(Instantiator $instantiator): ?object
}
$this->initialization = true;

// Get from cache
if (true === $this->cacheStrategy?->has($this)) {
$this->object = $this->cacheStrategy?->get($this);
$this->retrieved = true;
$this->calls($this->object, $instantiator);
// Get from cache only for shared services
if (true === $this->shared) {
if (true === $this->cacheStrategy?->has($this)) {
$this->object = $this->cacheStrategy?->get($this);
$this->retrieved = true;
$this->calls($this->object, $instantiator);
$this->initialization = false;

return $this->object;
return $this->object;
}
}

// Factory?
Expand All @@ -291,37 +321,32 @@ public function get(Instantiator $instantiator): ?object
throw ContainerException::exceptedFactory($this, $result);
}
}

$this->object = $result;
$this->assertNullable();
$this->retrieved = true;
$this->calls($this->object, $instantiator);
$this->cacheStrategy?->set($this, $this->object);

return $this->object;
} else {
$result = $instantiator->newInstanceOf($this->class, $this->getArguments());
}

$this->object = $instantiator->newInstanceOf($this->class, $this->getArguments());
$this->assertNullable();
$this->retrieved = true;
$this->calls($this->object, $instantiator);
$this->cacheStrategy?->set($this, $this->object);
true === $this->shared && $this->object = $result;
$this->assertNullable($result);
$this->retrieved = $this->shared;
$this->calls($result, $instantiator);
true === $this->shared && $this->cacheStrategy?->set($this, $result);
$this->initialization = false;

return $this->object;
return $result;
}

/**
* Assert nullable.
*
* @throws ContainerException
*/
protected function assertNullable(): void
protected function assertNullable(object|null $object): void
{
if (true === $this->nullable) {
return;
}

if (null === $this->object) {
if (null === $object) {
throw new ContainerException(sprintf('Service "%s" cannot be NULL', $this->getAlias()));
}
}
Expand Down
24 changes: 24 additions & 0 deletions tests/Service/ServiceTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
use Berlioz\ServiceContainer\Tests\Asset\RecursiveService;
use Berlioz\ServiceContainer\Tests\Asset\Service1;
use Berlioz\ServiceContainer\Tests\Asset\Service2;
use Berlioz\ServiceContainer\Tests\Asset\Service4;
use PHPUnit\Framework\TestCase;

class ServiceTest extends TestCase
Expand Down Expand Up @@ -73,6 +74,17 @@ public function testIsNullable()
$this->assertTrue($service->isNullable());
}

public function testIsShared()
{
$service = new Service(Service1::class);

$this->assertTrue($service->isShared());

$service->setShared(false);

$this->assertFalse($service->isShared());
}

public function testGetFactory()
{
$service = new Service(Service1::class, factory: $factory = fn(...$args) => new Service1(...$args));
Expand Down Expand Up @@ -179,6 +191,18 @@ public function testGet_withFactoryNullResult()
$this->assertEquals(1, $nbRetrieve);
}

public function testGet_notShared()
{
$service = new Service(Service4::class);
$service->setShared(false);

$this->assertInstanceOf(
Service4::class,
$object = $service->get(new Instantiator())
);
$this->assertNotSame($object, $service->get(new Instantiator()));
}

public function testGet_withBadResultFactory()
{
$this->expectException(ContainerException::class);
Expand Down

0 comments on commit 07489f3

Please sign in to comment.