From 1dd10c68a69918f233b383cb3214846478493793 Mon Sep 17 00:00:00 2001 From: Daniel Salcedo Date: Tue, 18 Aug 2026 09:04:32 -0600 Subject: [PATCH] Feature: add Octane compatibility --- README.md | 30 ++++++++++++++++++++++++++++++ src/Spotlight.php | 8 ++++++++ 2 files changed, 38 insertions(+) diff --git a/README.md b/README.md index a3c6d07..e1fa09d 100644 --- a/README.md +++ b/README.md @@ -319,6 +319,36 @@ class CreateUser extends SpotlightCommand } ``` +## Laravel Octane compatibility + +Spotlight keeps its registered commands in a static list that is populated once when the package (or your own +service provider) boots. Under Octane, provider `boot()` methods only run **once per worker**, not once per +request, so anything you pass to `registerCommand`, `registerCommandIf`, or `registerCommandUnless` from a service +provider is evaluated a single time when the worker starts. + +This is fine for conditions that don't change at runtime (e.g. config values or feature flags resolved at boot), +but it means you should **not** base these calls on per-request state such as the authenticated user: + +```php +// Bad under Octane: `auth()->check()` is only evaluated once, when the worker boots, +// so every request served by that worker will see the result frozen at boot time. +Spotlight::registerCommandIf(auth()->check(), CreateUser::class); +``` + +Instead, always register the command unconditionally and use the `shouldBeShown` method described above to decide +per-request whether it should be visible. `shouldBeShown` is resolved through the container on every render, so it +correctly reflects the current request/user under Octane: + +```php +Spotlight::registerCommand(CreateUser::class); +``` + +```php +public function shouldBeShown(Request $request): bool +{ + return $request->user()?->can('create user') ?? false; +} +``` ## Configuration diff --git a/src/Spotlight.php b/src/Spotlight.php index d870701..0a730dc 100644 --- a/src/Spotlight.php +++ b/src/Spotlight.php @@ -16,6 +16,14 @@ class Spotlight extends Component public static function registerCommand(string $command): void { + // Under Octane, service provider boot() methods only run once per + // worker instead of once per request, so this guards against + // duplicate/unbounded growth of the static command list if a + // provider is ever booted more than once within the same worker. + if (collect(self::$commands)->contains(fn (SpotlightCommand $registered) => $registered::class === $command)) { + return; + } + tap(new $command, function (SpotlightCommand $command) { self::$commands[] = $command; });