-
-
Notifications
You must be signed in to change notification settings - Fork 433
Description
What Happened
Classes injected into a controller's constructor that get modified as part of the request are not flushed when navigating to subsequent pages (either with navigate, click or refresh).
In our specific case, on the landing page, an API request is made which applies a criteria to a DB repository injected into the controller's constructor. The next page makes an API request to the same endpoint without the filter, however the criteria is still being applied to the DB query.
Injecting the repository class into the controller method works as expected. The issue only occurs when it's injected in the constructor.
How to Reproduce
The below is a simplified example for demonstration. There are two endpoints, one interacts with the constructor-injected class, the other with the method-injected class.
The first request to each endpoint sets a property on the injected class, the subsequent request doesn't and so expects the default value.
class Foo
{
public string $bar = 'default';
}class FooController
{
public function __construct(protected Foo $foo)
{
}
/**
* Use Foo from controller's constructor
*/
public function constructed(): string
{
if (request()->query('bar')) {
$this->foo->bar = request()->query('bar');
}
return $this->foo->bar;
}
/**
* Use Foo from method
*/
public function isolated(Foo $foo): string
{
if (request()->query('bar')) {
$foo->bar = request()->query('bar');
}
return $foo->bar;
}
}test('it flushes scope', function () {
Route::get('constructed', [FooController::class, 'constructed']);
Route::get('isolated', [FooController::class, 'isolated']);
// Visit isolated method, set bar
visit(url('isolated') . '?bar=qux')
->assertSee('qux')
// Navigate back to isolated method, see bar is reset
->navigate(url('isolated'))
->assertSee('default')
// Navigate to constructor method, set bar
->navigate(url('constructed') . '?bar=baz')
->assertSee('baz')
// Navigate back to constructor, see bar is reset
->navigate(url('constructed'))
->assertSee('default'); // <== ❌ Should see "default" but gets "baz";
});Sample Repository
No response
Pest Version
4.1.4
PHP Version
8.4.15
Operation System
Linux
Notes
Laravel 12.41.1
Adding the Scoped attribute to either Foo and/or FooController has no effect. I understand Octane runs in memory and so has guidance on what not to inject into constructors that get loaded on boot. Pest's browser plugin may require similar principles but this is a gotcha for us since we would expect the controller to be fresh on each request (we're not running on Octane).