From 773ee897183b5a41fa32db1b759b5122e546fd58 Mon Sep 17 00:00:00 2001 From: Luke Kuzmish Date: Fri, 31 Oct 2025 15:39:35 -0400 Subject: [PATCH 01/19] with cached routes --- src/Illuminate/Foundation/Application.php | 4 ++- .../Providers/RouteServiceProvider.php | 1 + .../Foundation/Testing/WithCachedRoutes.php | 31 +++++++++++++++++++ .../Foundation/FoundationApplicationTest.php | 25 +++++++++++++++ 4 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 src/Illuminate/Foundation/Testing/WithCachedRoutes.php diff --git a/src/Illuminate/Foundation/Application.php b/src/Illuminate/Foundation/Application.php index ef99215b2441..7be28d4424c1 100755 --- a/src/Illuminate/Foundation/Application.php +++ b/src/Illuminate/Foundation/Application.php @@ -1322,7 +1322,9 @@ public function getCachedConfigPath() */ public function routesAreCached() { - return $this['files']->exists($this->getCachedRoutesPath()); + return ($this->bound('routes.cached') && + $this->make('routes.cached') === true) || + $this['files']->exists($this->getCachedRoutesPath()); } /** diff --git a/src/Illuminate/Foundation/Support/Providers/RouteServiceProvider.php b/src/Illuminate/Foundation/Support/Providers/RouteServiceProvider.php index ad881b371193..d4d244ecab97 100644 --- a/src/Illuminate/Foundation/Support/Providers/RouteServiceProvider.php +++ b/src/Illuminate/Foundation/Support/Providers/RouteServiceProvider.php @@ -53,6 +53,7 @@ public function register() $this->booted(function () { $this->setRootControllerNamespace(); + // if ($this->routesAreCached()) { $this->loadCachedRoutes(); } else { diff --git a/src/Illuminate/Foundation/Testing/WithCachedRoutes.php b/src/Illuminate/Foundation/Testing/WithCachedRoutes.php new file mode 100644 index 000000000000..3ef69b36dbca --- /dev/null +++ b/src/Illuminate/Foundation/Testing/WithCachedRoutes.php @@ -0,0 +1,31 @@ +app->instance('routes.cached', true); + + if ((self::$cachedRoutes ?? null) === null) { + $routes = $this->app['router']->getRoutes(); + $routes->refreshNameLookups(); + $routes->refreshActionLookups(); + self::$cachedRoutes = $routes; + } + + RouteServiceProvider::loadCachedRoutesUsing( + static fn () => app('router')->setCompiledRoutes(self::$cachedRoutes) + ); + } + + protected function tearDownWithCachedRoutes(): void + { + RouteServiceProvider::loadCachedRoutesUsing(null); + } +} diff --git a/tests/Foundation/FoundationApplicationTest.php b/tests/Foundation/FoundationApplicationTest.php index d403e4a0702a..1c2983acf266 100755 --- a/tests/Foundation/FoundationApplicationTest.php +++ b/tests/Foundation/FoundationApplicationTest.php @@ -9,6 +9,7 @@ use Illuminate\Foundation\Events\LocaleUpdated; use Illuminate\Support\ServiceProvider; use Mockery as m; +use PHPUnit\Framework\Attributes\TestWith; use PHPUnit\Framework\TestCase; use stdClass; use Symfony\Component\HttpKernel\Exception\HttpException; @@ -609,6 +610,30 @@ public function testAbortAcceptsHeaders() $this->assertSame(['X-FOO' => 'BAR'], $exception->getHeaders()); } } + + public function test_routes_are_cached() + { + $app = new Application(); + $app->instance('routes.cached', true); + $this->assertTrue($app->routesAreCached()); + } + + public function test_routes_are_not_cached_by_instance_falls_back_to_file() + { + $app = new Application(); + $files = new class { + public string $pathRequested; + public function exists(string $path): bool + { + $this->pathRequested = $path; + return false; + } + }; + $app->instance('files', $files); + + $this->assertFalse($app->routesAreCached()); + $this->assertStringContainsString('routes-v7.php', $files->pathRequested); + } } class ApplicationBasicServiceProviderStub extends ServiceProvider From cd4000c6c9ef52badce4e1167d5a7bb527ef825f Mon Sep 17 00:00:00 2001 From: Luke Kuzmish Date: Fri, 31 Oct 2025 15:54:54 -0400 Subject: [PATCH 02/19] clean up --- .../Foundation/Support/Providers/RouteServiceProvider.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Illuminate/Foundation/Support/Providers/RouteServiceProvider.php b/src/Illuminate/Foundation/Support/Providers/RouteServiceProvider.php index d4d244ecab97..ad881b371193 100644 --- a/src/Illuminate/Foundation/Support/Providers/RouteServiceProvider.php +++ b/src/Illuminate/Foundation/Support/Providers/RouteServiceProvider.php @@ -53,7 +53,6 @@ public function register() $this->booted(function () { $this->setRootControllerNamespace(); - // if ($this->routesAreCached()) { $this->loadCachedRoutes(); } else { From e1ac69c0779bd2a1f81a8eebc11b43d94a1e2cb2 Mon Sep 17 00:00:00 2001 From: Luke Kuzmish Date: Fri, 31 Oct 2025 15:57:19 -0400 Subject: [PATCH 03/19] clean up --- src/Illuminate/Foundation/Testing/WithCachedRoutes.php | 4 ++-- tests/Foundation/FoundationApplicationTest.php | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Illuminate/Foundation/Testing/WithCachedRoutes.php b/src/Illuminate/Foundation/Testing/WithCachedRoutes.php index 3ef69b36dbca..bbd639863d34 100644 --- a/src/Illuminate/Foundation/Testing/WithCachedRoutes.php +++ b/src/Illuminate/Foundation/Testing/WithCachedRoutes.php @@ -10,8 +10,6 @@ trait WithCachedRoutes protected function setUpWithCachedRoutes(): void { - $this->app->instance('routes.cached', true); - if ((self::$cachedRoutes ?? null) === null) { $routes = $this->app['router']->getRoutes(); $routes->refreshNameLookups(); @@ -19,6 +17,8 @@ protected function setUpWithCachedRoutes(): void self::$cachedRoutes = $routes; } + $this->app->instance('routes.cached', true); + RouteServiceProvider::loadCachedRoutesUsing( static fn () => app('router')->setCompiledRoutes(self::$cachedRoutes) ); diff --git a/tests/Foundation/FoundationApplicationTest.php b/tests/Foundation/FoundationApplicationTest.php index 1c2983acf266..86c34b542f93 100755 --- a/tests/Foundation/FoundationApplicationTest.php +++ b/tests/Foundation/FoundationApplicationTest.php @@ -9,7 +9,6 @@ use Illuminate\Foundation\Events\LocaleUpdated; use Illuminate\Support\ServiceProvider; use Mockery as m; -use PHPUnit\Framework\Attributes\TestWith; use PHPUnit\Framework\TestCase; use stdClass; use Symfony\Component\HttpKernel\Exception\HttpException; @@ -621,7 +620,8 @@ public function test_routes_are_cached() public function test_routes_are_not_cached_by_instance_falls_back_to_file() { $app = new Application(); - $files = new class { + $files = new class + { public string $pathRequested; public function exists(string $path): bool { From 0490096ecbde8bb6682c4ec7e7ce8e9343f9b71a Mon Sep 17 00:00:00 2001 From: Luke Kuzmish <42181698+cosmastech@users.noreply.github.com> Date: Sat, 1 Nov 2025 07:53:05 -0400 Subject: [PATCH 04/19] try to guess how Taylor would format it --- src/Illuminate/Foundation/Application.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Illuminate/Foundation/Application.php b/src/Illuminate/Foundation/Application.php index 7be28d4424c1..afc89a11cc00 100755 --- a/src/Illuminate/Foundation/Application.php +++ b/src/Illuminate/Foundation/Application.php @@ -1322,9 +1322,9 @@ public function getCachedConfigPath() */ public function routesAreCached() { - return ($this->bound('routes.cached') && - $this->make('routes.cached') === true) || - $this['files']->exists($this->getCachedRoutesPath()); + return ($this->bound('routes.cached') + && $this->make('routes.cached') === true) + || $this['files']->exists($this->getCachedRoutesPath()); } /** From f4735581646264ff97392617ec994c2d220d35a9 Mon Sep 17 00:00:00 2001 From: Luke Kuzmish <42181698+cosmastech@users.noreply.github.com> Date: Sat, 1 Nov 2025 10:45:55 -0400 Subject: [PATCH 05/19] compile to array --- src/Illuminate/Foundation/Testing/WithCachedRoutes.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Illuminate/Foundation/Testing/WithCachedRoutes.php b/src/Illuminate/Foundation/Testing/WithCachedRoutes.php index bbd639863d34..08d101533478 100644 --- a/src/Illuminate/Foundation/Testing/WithCachedRoutes.php +++ b/src/Illuminate/Foundation/Testing/WithCachedRoutes.php @@ -14,7 +14,7 @@ protected function setUpWithCachedRoutes(): void $routes = $this->app['router']->getRoutes(); $routes->refreshNameLookups(); $routes->refreshActionLookups(); - self::$cachedRoutes = $routes; + self::$cachedRoutes = $routes->compile(); } $this->app->instance('routes.cached', true); From b606fdd1d2663612f4b4de42199405863d5ef918 Mon Sep 17 00:00:00 2001 From: Luke Kuzmish <42181698+cosmastech@users.noreply.github.com> Date: Sat, 1 Nov 2025 10:46:55 -0400 Subject: [PATCH 06/19] Update WithCachedRoutes.php --- src/Illuminate/Foundation/Testing/WithCachedRoutes.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Illuminate/Foundation/Testing/WithCachedRoutes.php b/src/Illuminate/Foundation/Testing/WithCachedRoutes.php index 08d101533478..9e4cfee1ba04 100644 --- a/src/Illuminate/Foundation/Testing/WithCachedRoutes.php +++ b/src/Illuminate/Foundation/Testing/WithCachedRoutes.php @@ -6,7 +6,7 @@ trait WithCachedRoutes { - protected static array $cachedRoutes = []; + protected static array $cachedRoutes; protected function setUpWithCachedRoutes(): void { From 45bc684f1c917f1b3c1de18336e120ce01c9e96f Mon Sep 17 00:00:00 2001 From: Luke Kuzmish Date: Sat, 1 Nov 2025 11:42:37 -0400 Subject: [PATCH 07/19] I think this is better --- .../Foundation/Testing/CachedState.php | 8 +++++ .../Foundation/Testing/TestCase.php | 4 +++ .../Foundation/Testing/WithCachedRoutes.php | 30 +++++++++++++------ 3 files changed, 33 insertions(+), 9 deletions(-) create mode 100644 src/Illuminate/Foundation/Testing/CachedState.php diff --git a/src/Illuminate/Foundation/Testing/CachedState.php b/src/Illuminate/Foundation/Testing/CachedState.php new file mode 100644 index 000000000000..79cd3e0e906b --- /dev/null +++ b/src/Illuminate/Foundation/Testing/CachedState.php @@ -0,0 +1,8 @@ +booting(fn () => $this->markRoutesCached($app)); + } + $app->make(Kernel::class)->bootstrap(); return $app; diff --git a/src/Illuminate/Foundation/Testing/WithCachedRoutes.php b/src/Illuminate/Foundation/Testing/WithCachedRoutes.php index 9e4cfee1ba04..4dcfad9f51c5 100644 --- a/src/Illuminate/Foundation/Testing/WithCachedRoutes.php +++ b/src/Illuminate/Foundation/Testing/WithCachedRoutes.php @@ -2,30 +2,42 @@ namespace Illuminate\Foundation\Testing; +use Illuminate\Foundation\Application; use Illuminate\Foundation\Support\Providers\RouteServiceProvider; trait WithCachedRoutes { - protected static array $cachedRoutes; - + /** + * After creating the routes once, we can cache them for the remaining tests. + * + * @return void + */ protected function setUpWithCachedRoutes(): void { - if ((self::$cachedRoutes ?? null) === null) { + // If we haven't stored the cached routes yet, then let's store them + // once so we can use them in the remaining tests. + if ((CachedState::$cachedRoutes ?? null) === null) { $routes = $this->app['router']->getRoutes(); $routes->refreshNameLookups(); $routes->refreshActionLookups(); - self::$cachedRoutes = $routes->compile(); + CachedState::$cachedRoutes = $routes->compile(); } - $this->app->instance('routes.cached', true); - - RouteServiceProvider::loadCachedRoutesUsing( - static fn () => app('router')->setCompiledRoutes(self::$cachedRoutes) - ); + $this->markRoutesCached($this->app); } protected function tearDownWithCachedRoutes(): void { RouteServiceProvider::loadCachedRoutesUsing(null); } + + protected function markRoutesCached(Application $app): void + { + $app->instance('routes.cached', true); + + RouteServiceProvider::loadCachedRoutesUsing( + static fn () => app('router')->setCompiledRoutes(CachedState::$cachedRoutes) + ); + } + } From 33a4800edf4964997b8b5c8faa8302f74062e509 Mon Sep 17 00:00:00 2001 From: Luke Kuzmish Date: Sat, 1 Nov 2025 11:47:19 -0400 Subject: [PATCH 08/19] comments --- src/Illuminate/Foundation/Testing/WithCachedRoutes.php | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/Illuminate/Foundation/Testing/WithCachedRoutes.php b/src/Illuminate/Foundation/Testing/WithCachedRoutes.php index 4dcfad9f51c5..dd0cfe6723af 100644 --- a/src/Illuminate/Foundation/Testing/WithCachedRoutes.php +++ b/src/Illuminate/Foundation/Testing/WithCachedRoutes.php @@ -26,11 +26,20 @@ protected function setUpWithCachedRoutes(): void $this->markRoutesCached($this->app); } + /** + * Reset the route service provider so it's not defaulting to loading cached routes. + * Helpful if some of the tests in the suite apply this trait while others do not. + * + * @return void + */ protected function tearDownWithCachedRoutes(): void { RouteServiceProvider::loadCachedRoutesUsing(null); } + /** + * Inform the container to treat routes as cached. + */ protected function markRoutesCached(Application $app): void { $app->instance('routes.cached', true); From 3c84de0f6bdb95d1d4e6368573d51155ae4e32cc Mon Sep 17 00:00:00 2001 From: Luke Kuzmish Date: Sat, 1 Nov 2025 11:48:44 -0400 Subject: [PATCH 09/19] lighter check first --- src/Illuminate/Foundation/Testing/TestCase.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Illuminate/Foundation/Testing/TestCase.php b/src/Illuminate/Foundation/Testing/TestCase.php index 54468e5296fe..f2f5f296db55 100644 --- a/src/Illuminate/Foundation/Testing/TestCase.php +++ b/src/Illuminate/Foundation/Testing/TestCase.php @@ -29,7 +29,7 @@ public function createApplication() { $app = require Application::inferBasePath().'/bootstrap/app.php'; - if (in_array(WithCachedRoutes::class, class_uses_recursive(self::class)) && isset(CachedState::$cachedRoutes)) { + if (isset(CachedState::$cachedRoutes) && in_array(WithCachedRoutes::class, class_uses_recursive(self::class))) { $app->booting(fn () => $this->markRoutesCached($app)); } From d5024c2bcf8513b25110df178c44a4bd7d7f2965 Mon Sep 17 00:00:00 2001 From: Luke Kuzmish Date: Sat, 1 Nov 2025 11:57:59 -0400 Subject: [PATCH 10/19] static --- src/Illuminate/Foundation/Testing/TestCase.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Illuminate/Foundation/Testing/TestCase.php b/src/Illuminate/Foundation/Testing/TestCase.php index f2f5f296db55..3394092581df 100644 --- a/src/Illuminate/Foundation/Testing/TestCase.php +++ b/src/Illuminate/Foundation/Testing/TestCase.php @@ -29,7 +29,7 @@ public function createApplication() { $app = require Application::inferBasePath().'/bootstrap/app.php'; - if (isset(CachedState::$cachedRoutes) && in_array(WithCachedRoutes::class, class_uses_recursive(self::class))) { + if (isset(CachedState::$cachedRoutes) && in_array(WithCachedRoutes::class, class_uses_recursive(static::class))) { $app->booting(fn () => $this->markRoutesCached($app)); } From ea9a089fc49a1415722ea2f2fdad03316a3b4ab0 Mon Sep 17 00:00:00 2001 From: Taylor Otwell Date: Mon, 3 Nov 2025 16:21:45 -0600 Subject: [PATCH 11/19] formatting --- src/Illuminate/Foundation/Application.php | 5 ++--- src/Illuminate/Foundation/Testing/TestCase.php | 3 ++- src/Illuminate/Foundation/Testing/WithCachedRoutes.php | 7 ++++--- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/Illuminate/Foundation/Application.php b/src/Illuminate/Foundation/Application.php index afc89a11cc00..c8680628b45b 100755 --- a/src/Illuminate/Foundation/Application.php +++ b/src/Illuminate/Foundation/Application.php @@ -1322,9 +1322,8 @@ public function getCachedConfigPath() */ public function routesAreCached() { - return ($this->bound('routes.cached') - && $this->make('routes.cached') === true) - || $this['files']->exists($this->getCachedRoutesPath()); + return ($this->bound('routes.cached') && $this->make('routes.cached') === true) || + $this['files']->exists($this->getCachedRoutesPath()); } /** diff --git a/src/Illuminate/Foundation/Testing/TestCase.php b/src/Illuminate/Foundation/Testing/TestCase.php index 3394092581df..dbf8bbd1a4ac 100644 --- a/src/Illuminate/Foundation/Testing/TestCase.php +++ b/src/Illuminate/Foundation/Testing/TestCase.php @@ -29,7 +29,8 @@ public function createApplication() { $app = require Application::inferBasePath().'/bootstrap/app.php'; - if (isset(CachedState::$cachedRoutes) && in_array(WithCachedRoutes::class, class_uses_recursive(static::class))) { + if (isset(CachedState::$cachedRoutes) && + in_array(WithCachedRoutes::class, class_uses_recursive(static::class))) { $app->booting(fn () => $this->markRoutesCached($app)); } diff --git a/src/Illuminate/Foundation/Testing/WithCachedRoutes.php b/src/Illuminate/Foundation/Testing/WithCachedRoutes.php index dd0cfe6723af..05b57052ef4d 100644 --- a/src/Illuminate/Foundation/Testing/WithCachedRoutes.php +++ b/src/Illuminate/Foundation/Testing/WithCachedRoutes.php @@ -14,12 +14,12 @@ trait WithCachedRoutes */ protected function setUpWithCachedRoutes(): void { - // If we haven't stored the cached routes yet, then let's store them - // once so we can use them in the remaining tests. if ((CachedState::$cachedRoutes ?? null) === null) { $routes = $this->app['router']->getRoutes(); + $routes->refreshNameLookups(); $routes->refreshActionLookups(); + CachedState::$cachedRoutes = $routes->compile(); } @@ -28,7 +28,8 @@ protected function setUpWithCachedRoutes(): void /** * Reset the route service provider so it's not defaulting to loading cached routes. - * Helpful if some of the tests in the suite apply this trait while others do not. + * + * This is helpful if some of the tests in the suite apply this trait while others do not. * * @return void */ From 1797e4f078b8cebab93a68eb193a55bf30640fe2 Mon Sep 17 00:00:00 2001 From: Luke Kuzmish Date: Sat, 1 Nov 2025 07:56:52 -0400 Subject: [PATCH 12/19] wip --- src/Illuminate/Foundation/Application.php | 4 ++- .../Bootstrap/LoadConfiguration.php | 23 ++++++++++++++++- .../Foundation/Testing/WithCachedConfig.php | 25 +++++++++++++++++++ 3 files changed, 50 insertions(+), 2 deletions(-) create mode 100644 src/Illuminate/Foundation/Testing/WithCachedConfig.php diff --git a/src/Illuminate/Foundation/Application.php b/src/Illuminate/Foundation/Application.php index c8680628b45b..e1db80e358a9 100755 --- a/src/Illuminate/Foundation/Application.php +++ b/src/Illuminate/Foundation/Application.php @@ -1302,7 +1302,9 @@ public function getCachedPackagesPath() */ public function configurationIsCached() { - return is_file($this->getCachedConfigPath()); + return ($this->bound('config.cached') + && $this->make('config.cached') === true) + || is_file($this->getCachedConfigPath()); } /** diff --git a/src/Illuminate/Foundation/Bootstrap/LoadConfiguration.php b/src/Illuminate/Foundation/Bootstrap/LoadConfiguration.php index 4c5f00e9a2c0..a1ef112541c8 100644 --- a/src/Illuminate/Foundation/Bootstrap/LoadConfiguration.php +++ b/src/Illuminate/Foundation/Bootstrap/LoadConfiguration.php @@ -2,6 +2,7 @@ namespace Illuminate\Foundation\Bootstrap; +use Closure; use Illuminate\Config\Repository; use Illuminate\Contracts\Config\Repository as RepositoryContract; use Illuminate\Contracts\Foundation\Application; @@ -11,6 +12,22 @@ class LoadConfiguration { + /** + * @var (Closure(Application): array)|null + */ + protected static ?Closure $alwaysUseConfig = null; + + /** + * Set a callback to return the config values. + * + * @param (Closure(Application): array)|null $alwaysUseConfig + * @return void + */ + public static function setAlwaysUseConfig(?Closure $alwaysUseConfig): void + { + static::$alwaysUseConfig = $alwaysUseConfig; + } + /** * Bootstrap the given application. * @@ -24,7 +41,11 @@ public function bootstrap(Application $app) // First we will see if we have a cache configuration file. If we do, we'll load // the configuration items from that file so that it is very quick. Otherwise // we will need to spin through every configuration file and load them all. - if (file_exists($cached = $app->getCachedConfigPath())) { + if (self::$alwaysUseConfig !== null) { + $items = $app->call(self::$alwaysUseConfig); + + $app->instance('config_loaded_from_cache', $loadedFromCache = true); + } elseif (file_exists($cached = $app->getCachedConfigPath())) { $items = require $cached; $app->instance('config_loaded_from_cache', $loadedFromCache = true); diff --git a/src/Illuminate/Foundation/Testing/WithCachedConfig.php b/src/Illuminate/Foundation/Testing/WithCachedConfig.php new file mode 100644 index 000000000000..c71abc2d4666 --- /dev/null +++ b/src/Illuminate/Foundation/Testing/WithCachedConfig.php @@ -0,0 +1,25 @@ +app->make('config')->all(); + } + + $this->app->instance('config.cached', true); + LoadConfiguration::setAlwaysUseConfig(static fn () => self::$cachedConfig); + } + + protected function tearDownWithCachedConfig(): void + { + LoadConfiguration::setAlwaysUseConfig(null); + } +} From 348aed83f299bf3c468a043b77e92efbffbcc8ae Mon Sep 17 00:00:00 2001 From: Luke Kuzmish Date: Mon, 3 Nov 2025 18:24:55 -0500 Subject: [PATCH 13/19] WithCachedConfig --- src/Illuminate/Foundation/Application.php | 8 ++++--- .../Bootstrap/LoadConfiguration.php | 6 ++++-- .../Foundation/Testing/CachedState.php | 1 + .../InteractsWithTestCaseLifecycle.php | 2 +- .../Foundation/Testing/TestCase.php | 14 ++++++++++++- .../Foundation/Testing/WithCachedConfig.php | 21 +++++++++++++------ 6 files changed, 39 insertions(+), 13 deletions(-) diff --git a/src/Illuminate/Foundation/Application.php b/src/Illuminate/Foundation/Application.php index e1db80e358a9..17aecc173419 100755 --- a/src/Illuminate/Foundation/Application.php +++ b/src/Illuminate/Foundation/Application.php @@ -1302,9 +1302,11 @@ public function getCachedPackagesPath() */ public function configurationIsCached() { - return ($this->bound('config.cached') - && $this->make('config.cached') === true) - || is_file($this->getCachedConfigPath()); + if ($this->bound('config_loaded_from_cache')) { + return (bool) $this->make('config_loaded_from_cache'); + } + + return $this->instance('config_loaded_from_cache', is_file($this->getCachedConfigPath())); } /** diff --git a/src/Illuminate/Foundation/Bootstrap/LoadConfiguration.php b/src/Illuminate/Foundation/Bootstrap/LoadConfiguration.php index a1ef112541c8..4660c1e6edeb 100644 --- a/src/Illuminate/Foundation/Bootstrap/LoadConfiguration.php +++ b/src/Illuminate/Foundation/Bootstrap/LoadConfiguration.php @@ -41,15 +41,17 @@ public function bootstrap(Application $app) // First we will see if we have a cache configuration file. If we do, we'll load // the configuration items from that file so that it is very quick. Otherwise // we will need to spin through every configuration file and load them all. + $loadedFromCache = false; if (self::$alwaysUseConfig !== null) { $items = $app->call(self::$alwaysUseConfig); - $app->instance('config_loaded_from_cache', $loadedFromCache = true); + $loadedFromCache = true; } elseif (file_exists($cached = $app->getCachedConfigPath())) { $items = require $cached; - $app->instance('config_loaded_from_cache', $loadedFromCache = true); + $loadedFromCache = true; } + $app->instance('config_loaded_from_cache', $loadedFromCache); // Next we will spin through all of the configuration files in the configuration // directory and load each one into the repository. This will make all of the diff --git a/src/Illuminate/Foundation/Testing/CachedState.php b/src/Illuminate/Foundation/Testing/CachedState.php index 79cd3e0e906b..4ecb14cbb9b0 100644 --- a/src/Illuminate/Foundation/Testing/CachedState.php +++ b/src/Illuminate/Foundation/Testing/CachedState.php @@ -5,4 +5,5 @@ class CachedState { public static array $cachedRoutes; + public static array $cachedConfig; } diff --git a/src/Illuminate/Foundation/Testing/Concerns/InteractsWithTestCaseLifecycle.php b/src/Illuminate/Foundation/Testing/Concerns/InteractsWithTestCaseLifecycle.php index 0daabf1ce139..ba01b2592768 100644 --- a/src/Illuminate/Foundation/Testing/Concerns/InteractsWithTestCaseLifecycle.php +++ b/src/Illuminate/Foundation/Testing/Concerns/InteractsWithTestCaseLifecycle.php @@ -203,7 +203,7 @@ protected function tearDownTheTestEnvironment(): void */ protected function setUpTraits() { - $uses = array_flip(class_uses_recursive(static::class)); + $uses = $this->testUsesTraits ?? array_flip(class_uses_recursive(static::class)); if (isset($uses[RefreshDatabase::class])) { $this->refreshDatabase(); diff --git a/src/Illuminate/Foundation/Testing/TestCase.php b/src/Illuminate/Foundation/Testing/TestCase.php index dbf8bbd1a4ac..bab19d657aed 100644 --- a/src/Illuminate/Foundation/Testing/TestCase.php +++ b/src/Illuminate/Foundation/Testing/TestCase.php @@ -20,6 +20,13 @@ abstract class TestCase extends BaseTestCase Concerns\InteractsWithTestCaseLifecycle, Concerns\InteractsWithViews; + /** + * The list of trait that this test uses, fetched recursively. + * + * @var array + */ + protected array $testUsesTraits; + /** * Creates the application. * @@ -29,10 +36,15 @@ public function createApplication() { $app = require Application::inferBasePath().'/bootstrap/app.php'; + $this->testUsesTraits = array_flip(class_uses_recursive(static::class)); if (isset(CachedState::$cachedRoutes) && - in_array(WithCachedRoutes::class, class_uses_recursive(static::class))) { + isset($this->testUsesTraits[WithCachedRoutes::class])) { $app->booting(fn () => $this->markRoutesCached($app)); } + if (isset(CachedState::$cachedRoutes) && + isset($this->testUsesTraits[WithCachedRoutes::class])) { + $app->booting(fn () => $this->markConfigCached($app)); + } $app->make(Kernel::class)->bootstrap(); diff --git a/src/Illuminate/Foundation/Testing/WithCachedConfig.php b/src/Illuminate/Foundation/Testing/WithCachedConfig.php index c71abc2d4666..7030dda598f7 100644 --- a/src/Illuminate/Foundation/Testing/WithCachedConfig.php +++ b/src/Illuminate/Foundation/Testing/WithCachedConfig.php @@ -2,24 +2,33 @@ namespace Illuminate\Foundation\Testing; +use Illuminate\Foundation\Application; use Illuminate\Foundation\Bootstrap\LoadConfiguration; +use Illuminate\Foundation\Support\Providers\RouteServiceProvider; trait WithCachedConfig { - protected static array $cachedConfig = []; - protected function setUpWithCachedConfig(): void { - if ((self::$cachedConfig ?? null) === null) { - self::$cachedConfig = $this->app->make('config')->all(); + if ((CachedState::$cachedConfig ?? null) === null) { + CachedState::$cachedConfig = $this->app->make('config')->all(); } - $this->app->instance('config.cached', true); - LoadConfiguration::setAlwaysUseConfig(static fn () => self::$cachedConfig); + $this->markConfigAsCached($this->app); } protected function tearDownWithCachedConfig(): void { LoadConfiguration::setAlwaysUseConfig(null); } + + /** + * Inform the container to treat configuration as cached. + */ + protected function markConfigAsCached(Application $app): void + { + $app->instance('config_loaded_from_cache', true); // I'm not sure this is actually needed + + LoadConfiguration::setAlwaysUseConfig(static fn () => CachedState::$cachedConfig); + } } From 4a5c4d05988da6f198fbf535ad32d736f5093636 Mon Sep 17 00:00:00 2001 From: Luke Kuzmish Date: Tue, 4 Nov 2025 06:37:21 -0500 Subject: [PATCH 14/19] thanks static analysis --- src/Illuminate/Foundation/Bootstrap/LoadConfiguration.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Illuminate/Foundation/Bootstrap/LoadConfiguration.php b/src/Illuminate/Foundation/Bootstrap/LoadConfiguration.php index 4660c1e6edeb..c1b24e5c1ded 100644 --- a/src/Illuminate/Foundation/Bootstrap/LoadConfiguration.php +++ b/src/Illuminate/Foundation/Bootstrap/LoadConfiguration.php @@ -58,7 +58,7 @@ public function bootstrap(Application $app) // options available to the developer for use in various parts of this app. $app->instance('config', $config = new Repository($items)); - if (! isset($loadedFromCache)) { + if (! $loadedFromCache) { $this->loadConfigurationFiles($app, $config); } From c8fc780839fb6024f6184852affe8228bab1403b Mon Sep 17 00:00:00 2001 From: Luke Kuzmish <42181698+cosmastech@users.noreply.github.com> Date: Tue, 4 Nov 2025 06:48:44 -0500 Subject: [PATCH 15/19] Update TestCase.php --- src/Illuminate/Foundation/Testing/TestCase.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Illuminate/Foundation/Testing/TestCase.php b/src/Illuminate/Foundation/Testing/TestCase.php index bab19d657aed..48759db5259c 100644 --- a/src/Illuminate/Foundation/Testing/TestCase.php +++ b/src/Illuminate/Foundation/Testing/TestCase.php @@ -41,8 +41,8 @@ public function createApplication() isset($this->testUsesTraits[WithCachedRoutes::class])) { $app->booting(fn () => $this->markRoutesCached($app)); } - if (isset(CachedState::$cachedRoutes) && - isset($this->testUsesTraits[WithCachedRoutes::class])) { + if (isset(CachedState::$cachedConfig) && + isset($this->testUsesTraits[WithCachedConfig::class])) { $app->booting(fn () => $this->markConfigCached($app)); } From 700fb370f3edb93b1007b10b180251672caee5d6 Mon Sep 17 00:00:00 2001 From: Luke Kuzmish <42181698+cosmastech@users.noreply.github.com> Date: Tue, 4 Nov 2025 06:49:00 -0500 Subject: [PATCH 16/19] Update WithCachedConfig.php --- src/Illuminate/Foundation/Testing/WithCachedConfig.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Illuminate/Foundation/Testing/WithCachedConfig.php b/src/Illuminate/Foundation/Testing/WithCachedConfig.php index 7030dda598f7..d15226d33c80 100644 --- a/src/Illuminate/Foundation/Testing/WithCachedConfig.php +++ b/src/Illuminate/Foundation/Testing/WithCachedConfig.php @@ -14,7 +14,7 @@ protected function setUpWithCachedConfig(): void CachedState::$cachedConfig = $this->app->make('config')->all(); } - $this->markConfigAsCached($this->app); + $this->markConfigCached($this->app); } protected function tearDownWithCachedConfig(): void @@ -25,7 +25,7 @@ protected function tearDownWithCachedConfig(): void /** * Inform the container to treat configuration as cached. */ - protected function markConfigAsCached(Application $app): void + protected function markConfigCached(Application $app): void { $app->instance('config_loaded_from_cache', true); // I'm not sure this is actually needed From 0cb7a123c176a96ab702855d846f4831e01bd11d Mon Sep 17 00:00:00 2001 From: Luke Kuzmish <42181698+cosmastech@users.noreply.github.com> Date: Tue, 4 Nov 2025 07:03:07 -0500 Subject: [PATCH 17/19] Update TestCase.php --- src/Illuminate/Foundation/Testing/TestCase.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Illuminate/Foundation/Testing/TestCase.php b/src/Illuminate/Foundation/Testing/TestCase.php index 48759db5259c..e14a909d9e9c 100644 --- a/src/Illuminate/Foundation/Testing/TestCase.php +++ b/src/Illuminate/Foundation/Testing/TestCase.php @@ -43,7 +43,7 @@ public function createApplication() } if (isset(CachedState::$cachedConfig) && isset($this->testUsesTraits[WithCachedConfig::class])) { - $app->booting(fn () => $this->markConfigCached($app)); + $this->markConfigCached($app); } $app->make(Kernel::class)->bootstrap(); From 420ea0c261e84bcc542086b69b12b71b721a6f48 Mon Sep 17 00:00:00 2001 From: Taylor Otwell Date: Fri, 7 Nov 2025 14:52:50 -0600 Subject: [PATCH 18/19] formatting --- .../Bootstrap/LoadConfiguration.php | 26 +++++++++++-------- .../InteractsWithTestCaseLifecycle.php | 2 +- .../Foundation/Testing/TestCase.php | 16 +++++++----- .../Foundation/Testing/WithCachedConfig.php | 11 ++++++-- 4 files changed, 34 insertions(+), 21 deletions(-) diff --git a/src/Illuminate/Foundation/Bootstrap/LoadConfiguration.php b/src/Illuminate/Foundation/Bootstrap/LoadConfiguration.php index c1b24e5c1ded..37229ac41a6a 100644 --- a/src/Illuminate/Foundation/Bootstrap/LoadConfiguration.php +++ b/src/Illuminate/Foundation/Bootstrap/LoadConfiguration.php @@ -13,21 +13,12 @@ class LoadConfiguration { /** + * The closure that resolves the permanent, static configuration if applicable. + * * @var (Closure(Application): array)|null */ protected static ?Closure $alwaysUseConfig = null; - /** - * Set a callback to return the config values. - * - * @param (Closure(Application): array)|null $alwaysUseConfig - * @return void - */ - public static function setAlwaysUseConfig(?Closure $alwaysUseConfig): void - { - static::$alwaysUseConfig = $alwaysUseConfig; - } - /** * Bootstrap the given application. * @@ -42,6 +33,7 @@ public function bootstrap(Application $app) // the configuration items from that file so that it is very quick. Otherwise // we will need to spin through every configuration file and load them all. $loadedFromCache = false; + if (self::$alwaysUseConfig !== null) { $items = $app->call(self::$alwaysUseConfig); @@ -51,6 +43,7 @@ public function bootstrap(Application $app) $loadedFromCache = true; } + $app->instance('config_loaded_from_cache', $loadedFromCache); // Next we will spin through all of the configuration files in the configuration @@ -218,4 +211,15 @@ protected function getBaseConfiguration() return $config; } + + /** + * Set a callback to return the permanent, static configuration values. + * + * @param (Closure(Application): array)|null $alwaysUseConfig + * @return void + */ + public static function alwaysUse(?Closure $alwaysUseConfig): void + { + static::$alwaysUseConfig = $alwaysUseConfig; + } } diff --git a/src/Illuminate/Foundation/Testing/Concerns/InteractsWithTestCaseLifecycle.php b/src/Illuminate/Foundation/Testing/Concerns/InteractsWithTestCaseLifecycle.php index ba01b2592768..860c7a4b47f5 100644 --- a/src/Illuminate/Foundation/Testing/Concerns/InteractsWithTestCaseLifecycle.php +++ b/src/Illuminate/Foundation/Testing/Concerns/InteractsWithTestCaseLifecycle.php @@ -203,7 +203,7 @@ protected function tearDownTheTestEnvironment(): void */ protected function setUpTraits() { - $uses = $this->testUsesTraits ?? array_flip(class_uses_recursive(static::class)); + $uses = $this->traitsUsedByTest ?? array_flip(class_uses_recursive(static::class)); if (isset($uses[RefreshDatabase::class])) { $this->refreshDatabase(); diff --git a/src/Illuminate/Foundation/Testing/TestCase.php b/src/Illuminate/Foundation/Testing/TestCase.php index e14a909d9e9c..0b5acfd37662 100644 --- a/src/Illuminate/Foundation/Testing/TestCase.php +++ b/src/Illuminate/Foundation/Testing/TestCase.php @@ -25,7 +25,7 @@ abstract class TestCase extends BaseTestCase * * @var array */ - protected array $testUsesTraits; + protected array $traitsUsedByTest; /** * Creates the application. @@ -36,16 +36,18 @@ public function createApplication() { $app = require Application::inferBasePath().'/bootstrap/app.php'; - $this->testUsesTraits = array_flip(class_uses_recursive(static::class)); - if (isset(CachedState::$cachedRoutes) && - isset($this->testUsesTraits[WithCachedRoutes::class])) { - $app->booting(fn () => $this->markRoutesCached($app)); - } + $this->traitsUsedByTest = array_flip(class_uses_recursive(static::class)); + if (isset(CachedState::$cachedConfig) && - isset($this->testUsesTraits[WithCachedConfig::class])) { + isset($this->traitsUsedByTest[WithCachedConfig::class])) { $this->markConfigCached($app); } + if (isset(CachedState::$cachedRoutes) && + isset($this->traitsUsedByTest[WithCachedRoutes::class])) { + $app->booting(fn () => $this->markRoutesCached($app)); + } + $app->make(Kernel::class)->bootstrap(); return $app; diff --git a/src/Illuminate/Foundation/Testing/WithCachedConfig.php b/src/Illuminate/Foundation/Testing/WithCachedConfig.php index d15226d33c80..545a88ef4a65 100644 --- a/src/Illuminate/Foundation/Testing/WithCachedConfig.php +++ b/src/Illuminate/Foundation/Testing/WithCachedConfig.php @@ -4,10 +4,12 @@ use Illuminate\Foundation\Application; use Illuminate\Foundation\Bootstrap\LoadConfiguration; -use Illuminate\Foundation\Support\Providers\RouteServiceProvider; trait WithCachedConfig { + /** + * After resolving the configuration once, we can cache it for the remaining tests. + */ protected function setUpWithCachedConfig(): void { if ((CachedState::$cachedConfig ?? null) === null) { @@ -17,13 +19,18 @@ protected function setUpWithCachedConfig(): void $this->markConfigCached($this->app); } + /** + * Reset the cached configuration. + * + * This is helpful if some of the tests in the suite apply this trait while others do not. + */ protected function tearDownWithCachedConfig(): void { LoadConfiguration::setAlwaysUseConfig(null); } /** - * Inform the container to treat configuration as cached. + * Inform the container that the configuration is cached. */ protected function markConfigCached(Application $app): void { From a65ebac8117723cc0e4461e24904c0bdbd12b717 Mon Sep 17 00:00:00 2001 From: Taylor Otwell Date: Fri, 7 Nov 2025 14:53:27 -0600 Subject: [PATCH 19/19] Update WithCachedConfig.php --- src/Illuminate/Foundation/Testing/WithCachedConfig.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Illuminate/Foundation/Testing/WithCachedConfig.php b/src/Illuminate/Foundation/Testing/WithCachedConfig.php index 545a88ef4a65..41d0cdcae3ca 100644 --- a/src/Illuminate/Foundation/Testing/WithCachedConfig.php +++ b/src/Illuminate/Foundation/Testing/WithCachedConfig.php @@ -36,6 +36,6 @@ protected function markConfigCached(Application $app): void { $app->instance('config_loaded_from_cache', true); // I'm not sure this is actually needed - LoadConfiguration::setAlwaysUseConfig(static fn () => CachedState::$cachedConfig); + LoadConfiguration::alwaysUse(static fn () => CachedState::$cachedConfig); } }