Repository navigation
Description
Laravel Version
13.30.0 and 13.30.1 (13.29.0 is fine)
PHP Version
8.5.10 (also 8.5.9)
Database Driver & Version
Not involved. Reproduced on the default SQLite of a fresh install and on PostgreSQL 17.
Description
Since #61346 (13.30.0) RouteCacheCommand::getFreshApplication() boots a throwaway Application and afterwards restores the facade root to the live application:
Facade::clearResolvedInstances();
Facade::setFacadeApplication($this->laravel);new Application also calls Container::setInstance($this) (in registerBaseBindings()), and nothing restores that. So after route:cache the process is in a split state: facades resolve against the live app, while Container::getInstance() / app() resolve against the discarded one. Before 13.30 both pointed at the throwaway app, which was equally wrong but self-consistent, so it never showed.
optimize runs view:cache right after route:cache in the same process, and view:cache falls into the split:
ViewClearCommand/ViewCacheCommandresolve the Blade engine through$this->laravel['view.engine.resolver']->resolve('blade'), i.e. on the live app.- The
bladeengine closure inViewServiceProvider::registerBladeEngine()builds the engine fromContainer::getInstance()->make('blade.compiler'), i.e. the throwaway app's compiler. - That resolution fires the
afterResolving('blade.compiler')hooks. A package that registers class component namespaces there through theBladefacade (inertia-laravel 3.x does:Blade::componentNamespace('Inertia\\View\\Components', 'inertia')) registers them on the live app's compiler instead. - The compiler that actually compiles has an empty
classComponentNamespaces, and the first<x-inertia::...>tag fails:
views .......................................................... 9.32ms FAIL
In ComponentTagCompiler.php line 315:
Unable to locate a class or view for component [inertia::head].
php artisan view:cache on its own succeeds (no route:cache ran before it in that process). 13.29.0 succeeds. 13.30.x with getFreshApplication() reverted to the 13.29 body succeeds.
Instrumented run on 13.30.0 (ids from spl_object_id; #4 is the live app, #2531 the throwaway app booted by route:cache):
inertia callback: providerApp#2531 passedCompiler#4100 facadeApp#4 facadeCompiler#4463
componentClass(inertia::app): compiler#4100 namespaces=[] facadeApp#4 container#2531
The namespace went to compiler #4463, the compilation ran on #4100.
Inertia could dodge this particular symptom by using the compiler instance passed to its callback instead of the facade (reported separately to inertiajs/inertia-laravel), but the split between Facade::getFacadeApplication() and Container::getInstance() is in the framework and affects anything that runs after route:cache in the same process and goes through app() / Container::getInstance().
Steps To Reproduce
composer create-project laravel/laravel repro # 13.30.1
cd repro
composer require inertiajs/inertia-laravel # 3.3.1
cat > resources/views/app.blade.php <<'BLADE'
<!DOCTYPE html>
<html>
<head><x-inertia::head /></head>
<body><x-inertia::app /></body>
</html>
BLADE
php artisan optimize # views FAIL: Unable to locate a class or view for component [inertia::head]
php artisan optimize:clear
php artisan view:cache # OK
composer require laravel/framework:13.29.0 -W
php artisan optimize # config / events / routes / views all DONESuggested fix
Restore the container instance together with the facade root:
protected function getFreshApplication()
{
return tap(require $this->laravel->bootstrapPath('app.php'), function ($app) {
$app->make(ConsoleKernelContract::class)->bootstrap();
Facade::clearResolvedInstances();
Facade::setFacadeApplication($this->laravel);
Container::setInstance($this->laravel);
});
}ConfigCacheCommand::getFreshConfiguration() boots a throwaway app the same way and leaves Container::getInstance() on it too; #61350 / #61351 proposed the facade-only restore for it, so whatever lands there should keep the two in sync as well.
Workarounds until then: run config:cache, event:cache, route:cache, view:cache as separate processes instead of optimize, or pin laravel/framework:13.29.0.
Activity