Laravel 11, Pennant, and Conditional Scheduled Jobs

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.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.