Octane rebinds the container per request, and an object that captured a dependency at construction keeps the old one.
// the shape that breaks
final class Reporter
{
public function __construct(private Request $request) {}
// $request is now request #1's, forever
}
// the shape that does not
final class Reporter
{
public function __construct(private Container $app) {}
private function request(): Request
{
return $this->app->make(Request::class);
}
}
Injecting the container to avoid capturing is a pattern that reads badly and is correct here, which is an uncomfortable combination. The alternative — passing the request as a method argument rather than a constructor argument — is cleaner and requires changing every caller. Octane ships listeners to flush known framework state, and they cover the framework rather than your code, so the singletons registered in your own service providers are where the work is.