Skip to content

Commit

Permalink
Store the autowired services in original properties and allow their o…
Browse files Browse the repository at this point in the history
…verwriting
  • Loading branch information
xificurk committed Sep 12, 2022
1 parent a3b12b8 commit b451369
Show file tree
Hide file tree
Showing 3 changed files with 5 additions and 45 deletions.
2 changes: 1 addition & 1 deletion docs/en/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ Every `protected` or `public` property marked with `#[Autowire]` attribute will

The properties are analysed and result of the analysis is cached. This means, that you will see errors in your configuration instantly, and not after you use it in some conditional code, that might not even be executed every time. This is here to help you find errors, as early as possible.

Every autowired property will be unsetted, when presenter is created, and then the trait takes over using `__get()` and `__set()` magic. The service will be created only if it's really used and it cannot be overwritten, once it has some value.
Every autowired property will be unsetted, when presenter is created, and then the trait takes over using `__get()` magic. The service will be created only if it's really used.

This behaviour is inspired by article [DI and property injection](http://phpfashion.com/di-a-property-injection) by [David Grudl](http://davidgrudl.com/).

Expand Down
5 changes: 0 additions & 5 deletions phpstan-baseline.neon
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,6 @@ parameters:
count: 1
path: tests/KdybyTests/Autowired/PropertiesFixtures/NonPresenterComponent.php

-
message: "#^KdybyTests\\\\Autowired\\\\PropertiesFixtures\\\\NonPresenterComponent\\:\\:__set\\(\\) calls parent\\:\\:__set\\(\\) but KdybyTests\\\\Autowired\\\\PropertiesFixtures\\\\NonPresenterComponent does not extend any class\\.$#"
count: 1
path: tests/KdybyTests/Autowired/PropertiesFixtures/NonPresenterComponent.php

-
message: "#^Parameter \\#1 \\$componentClass of method Kdyby\\\\Autowired\\\\Caching\\\\CacheFactory\\:\\:create\\(\\) expects class\\-string\\<Nette\\\\Application\\\\UI\\\\Component\\>, class\\-string\\<static\\(KdybyTests\\\\Autowired\\\\PropertiesFixtures\\\\NonPresenterComponent\\)\\> given\\.$#"
count: 1
Expand Down
43 changes: 4 additions & 39 deletions src/Kdyby/Autowired/AutowireProperties.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,6 @@ trait AutowireProperties
*/
private array $autowirePropertiesMeta = [];

/**
* @var array<string, object>
*/
private array $autowireProperties = [];

private Nette\DI\Container $autowirePropertiesLocator;

/**
Expand Down Expand Up @@ -112,7 +107,7 @@ private function resolveProperty(\ReflectionProperty $prop): void
$this->getAutowiredService($metadata['type'], 'service', $prop);
}

// unset property to pass control to __set() and __get()
// unset property to pass control to __get()
unset($this->{$prop->getName()});
$this->autowirePropertiesMeta[$prop->getName()] = $metadata;
}
Expand Down Expand Up @@ -156,47 +151,17 @@ private function resolvePropertyType(\ReflectionProperty $prop): string
return $type;
}

/**
* @param string $name
* @param mixed $value
* @throws MemberAccessException
* @return void
*/
public function __set(string $name, mixed $value): void
{
if (! isset($this->autowirePropertiesMeta[$name])) {
parent::__set($name, $value);
return;

}

if (isset($this->autowireProperties[$name])) {
throw new MemberAccessException("Property \$$name has already been set.");

}

if (! $value instanceof $this->autowirePropertiesMeta[$name]['type']) {
throw new MemberAccessException("Property \$$name must be an instance of " . $this->autowirePropertiesMeta[$name]['type'] . '.');
}

$this->autowireProperties[$name] = $value;
}

/**
* @throws MemberAccessException
* @return mixed
*/
public function &__get(string $name): mixed
{
if (! isset($this->autowirePropertiesMeta[$name])) {
return parent::__get($name);
}

if (! isset($this->autowireProperties[$name])) {
$this->autowireProperties[$name] = $this->createAutowiredPropertyService($name);
if (! isset($this->{$name})) {
$this->{$name} = $this->createAutowiredPropertyService($name);
}

return $this->autowireProperties[$name];
return $this->{$name};
}

private function createAutowiredPropertyService(string $name): object
Expand Down

0 comments on commit b451369

Please sign in to comment.