All packages
Options for Laravel
Observers
Observers react to one specific option changing, without a global listener that filters by key. Register them in a service provider’s boot():
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Cache;
use RoundlyConsulting\Options\DataTransferObjects\OptionChange;
use RoundlyConsulting\Options\Enums\OptionChangeType;
use RoundlyConsulting\Options\Facades\Options;
Options::observe(ThemeOption::class, function (mixed $value, ?Model $owner, OptionChange $change): void {
// $change->type is OptionChangeType::Set or ::Forgotten
Cache::forget('compiled-theme');
});
// Invokable class-string (resolved from the container), registered by key:
Options::observe('theme', RecompileThemeListener::class);
Options::forgetObservers(ThemeOption::class); // drop one option’s observers
Options::flushObservers(); // drop them allInvokable observers
A class-string observer is resolved from the container on each change, so constructor injection works:
use Illuminate\Database\Eloquent\Model;
use RoundlyConsulting\Options\DataTransferObjects\OptionChange;
final class RecompileThemeListener
{
public function __construct(private ThemeCompiler $compiler) {}
public function __invoke(mixed $value, ?Model $owner, OptionChange $change): void
{
$this->compiler->compileFor($owner);
}
}A class-string without __invoke throws InvalidOptionObserver when you register it.
The change payload
Every observer receives (mixed $value, ?Model $owner, OptionChange $change):
| Property | Type | Meaning |
|---|---|---|
key | string | The option’s key(). |
optionClass | class-string | The option class that changed. |
type | OptionChangeType | OptionChangeType::Set or OptionChangeType::Forgotten. |
value | mixed | The new value, cast — the same value get() returns. null for a forgotten option. |
owner | ?Model | The scope that changed — null for the global scope. |
Rules
- Observers fire on set() and forget(), in registration order — never on reads.
- Registering by class-string or by registry key targets the same option.
- They ride OptionSet and OptionForgotten, so they need options.events.enabled — except under Options::fake(), which fires them directly.
Show your open-source love
This package is free and MIT-licensed. If it saves you time, a one-off donation or a Patreon membership keeps it maintained, tested and documented.
More ways to support, including cryptoBy donating, you agree to our donation terms.
Want this built into your product?
We integrate our packages into custom Laravel and AI builds. Tell us what you're working on and we'll reply within 48 hours.