TL;DR: pass a function instead of Feature::active(…)
to your console jobs’ ->when(…)
method.
I recently upgraded an app from Laravel 10 to Laravel 11 (I know, I know…I’m a few months behind).
This app was using Laravel Pennant to conditionally register some jobs, based on feature flags:
Schedule::job(GetNewOrders::class)
->when(Feature::active(GetOrders::class))
->everyFiveMinutes();
Laravel Shift moved these jobs from app/Console/Kernel.php
to routes/console.php
as expected for the new Laravel 11 structure.
However, for every test that I ran, I was getting these errors:
Base table or view not found: 1146 Table 'test_database.features' doesn't exist
I spent a bit of time troubleshooting and verifying that the migration existed, the database schema was squashed, etc. I was expecting it to fail during the setUpTraits()
step of booting the framework, but it actually failed while booting the application. I stepped through more of the setup steps (thanks, xdebug!) and realized that it failed while discovering commands.
That prompted me to comment out the ->when(Feature::active(…))
lines, and voila! my tests suddenly worked!
The when()
method accepts either a boolean or a Closure
, so I tried wrapping the feature flag in a closure, and my tests still worked:
Schedule::job(GetNewOrders::class)
->when(fn () => Feature::active(GetOrders::class))
->everyFiveMinutes();
It appears that if your scheduled job ->when(…)
conditions depend on the database, you’ll want to wrap them in a function so they aren’t evaluated until they’re actually needed, after the database has already been set up.