Reputation: 423
EDIT1: I am trying to bind a singleton instance to the container, that has specified args and sometimes other dependencies (from the container) and I want to be able to get this instance via class name and also unset all instances that where constructed this way when I need to (which is typicall when I want to lose their state and initialize them with new arguments).
I've currently been struggling on unsetting a scoped instance from laravels DI container. To reproduce and unserstand, please see the following test:
it('should be able to remove scoped instances', function () {
class TestClass
{
public function __construct(
public int $count,
) {
}
}
function testResolveClass($class, array $args = []): object
{
if (! app()->bound($class)) {
$instance = app($class, $args);
app()->scoped($class, fn (Application $app) => $instance);
}
return app($class);
}
// Create first instance
$instance = testResolveClass(TestClass::class, ['count' => 123]);
$id = spl_object_id($instance);
// Unset instances
unset($instance);
app()->forgetScopedInstances(); // TODO Why doesnt this unset the instance?
// unset(app()[TestClass::class]); // would work because it also unsets the variables 'binding' and 'resolved', but cannot be done in my case
// Create another instance (at least we try to...)
$instance = testResolveClass(TestClass::class, ['count' => 456]);
$id2 = spl_object_id($instance);
// Expect the object id is not the same and the count changed
expect()
->and($id2)->not->toBe($id) // fails because id is the same
->and($instance->count)->toBe(456); // would fail because count is 123
});
Is my approach wrong, am I missing something or would you expect this behaviour aswell?
If I could check if the instance was forgotten, I could at least rebind the instance manually, but I cannot seem to find any check if a scoped instance is really bound or was unbound after calling app()->forgetScopedInstances();
.
Many thanks, michiruf
Upvotes: 0
Views: 50
Reputation: 7618
Your test code is invalid. In your test you use:
$instance = app($class, $args);
app()->scoped($class, fn (Application $app) => $instance);
It seems wrong to me to retrieve the instance from the container in the first line and then return it as part of a scoped instance in the second one.
When you change your code to the following, it will likely work as expected:
// No $instance variable here used.
app()->scoped($class, fn (\Illuminate\Foundation\Application $app) => new $class(...$args));
Upvotes: 0