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
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
Share Improve this question asked yesterday michirufmichiruf 4231 gold badge7 silver badges13 bronze badges1 Answer
Reset to default 0Your 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));