-
-
Notifications
You must be signed in to change notification settings - Fork 44
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add ability to use container as a factory #354
base: master
Are you sure you want to change the base?
Changes from all commits
897f257
85c77a8
898916f
f6856a6
684e8c0
9ddc47e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -35,7 +35,8 @@ | |
{ | ||
private const META_TAGS = 'tags'; | ||
private const META_RESET = 'reset'; | ||
private const ALLOWED_META = [self::META_TAGS, self::META_RESET]; | ||
private const META_AFTER_BUILT = 'afterBuilt'; | ||
private const ALLOWED_META = [self::META_TAGS, self::META_RESET, self::META_AFTER_BUILT]; | ||
|
||
/** | ||
* @var DefinitionStorage Storage of object definitions. | ||
|
@@ -67,6 +68,12 @@ | |
* @var Closure[] | ||
*/ | ||
private array $resetters = []; | ||
|
||
/** | ||
* @var Closure[] | ||
*/ | ||
public array $afterBuiltHooks = []; | ||
|
||
private bool $useResettersFromMeta = true; | ||
|
||
/** | ||
|
@@ -134,10 +141,12 @@ | |
*/ | ||
public function get(string $id) | ||
{ | ||
$result = null; | ||
if (!array_key_exists($id, $this->instances)) { | ||
try { | ||
try { | ||
$this->instances[$id] = $this->build($id); | ||
/** @psalm-suppress MixedAssignment */ | ||
$result = $this->instances[$id] = $this->build($id); | ||
} catch (NotFoundExceptionInterface $e) { | ||
if (!$this->delegates->has($id)) { | ||
throw $e; | ||
|
@@ -153,6 +162,7 @@ | |
throw new BuildingException($id, $e, $this->definitions->getBuildStack(), $e); | ||
} | ||
} | ||
$this->callHookAfterBuilt($id); | ||
|
||
if ($id === StateResetter::class) { | ||
$delegatesResetter = null; | ||
|
@@ -184,7 +194,7 @@ | |
} | ||
|
||
/** @psalm-suppress MixedReturnStatement */ | ||
return $this->instances[$id]; | ||
return $result ?? $this->instances[$id]; | ||
Check warning on line 197 in src/Container.php GitHub Actions / mutation / PHP 8.1-ubuntu-latest
Check warning on line 197 in src/Container.php GitHub Actions / mutation / PHP 8.1-ubuntu-latest
|
||
} | ||
|
||
/** | ||
|
@@ -206,7 +216,7 @@ | |
$this->validateMeta($meta); | ||
} | ||
/** | ||
* @psalm-var array{reset?:Closure,tags?:string[]} $meta | ||
* @psalm-var array{reset?:Closure,tags?:string[],afterBuilt?:Closure} $meta | ||
*/ | ||
|
||
if (isset($meta[self::META_TAGS])) { | ||
|
@@ -215,6 +225,9 @@ | |
if (isset($meta[self::META_RESET])) { | ||
$this->setDefinitionResetter($id, $meta[self::META_RESET]); | ||
} | ||
if (isset($meta[self::META_AFTER_BUILT])) { | ||
$this->setAfterBuiltHook($id, $meta[self::META_AFTER_BUILT]); | ||
} | ||
|
||
unset($this->instances[$id]); | ||
$this->addDefinitionToStorage($id, $definition); | ||
|
@@ -276,7 +289,7 @@ | |
|
||
$this->delegates->attach($delegate); | ||
} | ||
$this->definitions->setDelegateContainer($this->delegates); | ||
Check warning on line 292 in src/Container.php GitHub Actions / mutation / PHP 8.1-ubuntu-latest
Check warning on line 292 in src/Container.php GitHub Actions / mutation / PHP 8.1-ubuntu-latest
|
||
} | ||
|
||
/** | ||
|
@@ -303,7 +316,7 @@ | |
|
||
$definition = array_merge( | ||
$class === null ? [] : [ArrayDefinition::CLASS_NAME => $class], | ||
[ArrayDefinition::CONSTRUCTOR => $constructorArguments], | ||
Check warning on line 319 in src/Container.php GitHub Actions / mutation / PHP 8.1-ubuntu-latest
Check warning on line 319 in src/Container.php GitHub Actions / mutation / PHP 8.1-ubuntu-latest
|
||
// extract only value from parsed definition method | ||
array_map(fn (array $data): mixed => $data[2], $methodsAndProperties), | ||
); | ||
|
@@ -489,7 +502,7 @@ | |
); | ||
} | ||
|
||
$this->building[$id] = 1; | ||
Check warning on line 505 in src/Container.php GitHub Actions / mutation / PHP 8.1-ubuntu-latest
Check warning on line 505 in src/Container.php GitHub Actions / mutation / PHP 8.1-ubuntu-latest
|
||
try { | ||
/** @var mixed $object */ | ||
$object = $this->buildInternal($id); | ||
|
@@ -621,4 +634,16 @@ | |
|
||
return $providerInstance; | ||
} | ||
|
||
private function callHookAfterBuilt(string $id): void | ||
{ | ||
if (isset($this->afterBuiltHooks[$id])) { | ||
$this->afterBuiltHooks[$id]->call($this, $this, $id); | ||
} | ||
} | ||
|
||
private function setAfterBuiltHook(string $id, Closure $callback): void | ||
{ | ||
$this->afterBuiltHooks[$id] = $callback; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Yiisoft\Di\Hook; | ||
|
||
use Closure; | ||
use Yiisoft\Di\Container; | ||
|
||
final class AfterBuiltHook | ||
{ | ||
public static function unsetInstance(): Closure | ||
{ | ||
return function (Container $container, string $id) { | ||
/** | ||
* @var $this Container | ||
*/ | ||
/** @psalm-scope-this Container */ | ||
unset($this->instances[$id]); | ||
Check failure on line 19 in src/Hook/AfterBuiltHook.php GitHub Actions / psalm / PHP 8.0-ubuntu-latestUndefinedDocblockClass
Check failure on line 19 in src/Hook/AfterBuiltHook.php GitHub Actions / psalm / PHP 8.0-ubuntu-latestInvalidScope
Check failure on line 19 in src/Hook/AfterBuiltHook.php GitHub Actions / psalm / PHP 8.0-ubuntu-latestUndefinedDocblockClass
|
||
}; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Unit\Hook; | ||
|
||
use PHPUnit\Framework\TestCase; | ||
use Yiisoft\Di\Container; | ||
use Yiisoft\Di\ContainerConfig; | ||
use Yiisoft\Di\Hook\AfterBuiltHook; | ||
use Yiisoft\Di\Tests\Support\EngineInterface; | ||
use Yiisoft\Di\Tests\Support\EngineMarkOne; | ||
|
||
final class AfterBuiltHookTest extends TestCase | ||
{ | ||
public function testDifferentObjects() | ||
{ | ||
$config = ContainerConfig::create() | ||
->withDefinitions([ | ||
EngineInterface::class => [ | ||
'class' => EngineMarkOne::class, | ||
'afterBuilt' => AfterBuiltHook::unsetInstance(), | ||
], | ||
]); | ||
$container = new Container($config); | ||
|
||
$this->assertNotSame( | ||
$container->get(EngineInterface::class), | ||
$container->get(EngineInterface::class), | ||
); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are there any other cases for this hook?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not now