spatie/laravel-settings
Store strongly typed app settings in Laravel using dedicated Settings classes backed by databases, Redis, and more. Inject settings via the container, read and update properties, then save—keeping configuration structured, testable, and easy to manage.
## Getting Started
### Minimal Steps to Begin
1. **Installation**
```bash
composer require spatie/laravel-settings
php artisan vendor:publish --provider="Spatie\LaravelSettings\LaravelSettingsServiceProvider" --tag="migrations"
php artisan vendor:publish --provider="Spatie\LaravelSettings\LaravelSettingsServiceProvider" --tag="config"
php artisan migrate
Create a Settings Class
php artisan make:setting GeneralSettings --group=general
This generates a class in app/Settings/GeneralSettings.php:
class GeneralSettings extends Settings {
public string $site_name = 'Default Site';
public bool $site_active = true;
public static function group(): string {
return 'general';
}
}
Register the Settings Class
Add the class to config/settings.php under the settings array:
'settings' => [
Spatie\LaravelSettings\Settings\GeneralSettings::class,
],
Create a Migration
php artisan make:settings-migration CreateGeneralSettings
Define defaults in database/settings/YYYY_MM_DD_CreateGeneralSettings.php:
public function up(): void {
$this->migrator->add('general.site_name', 'My App');
$this->migrator->add('general.site_active', true);
}
Run migrations:
php artisan migrate
Use in Code Inject the settings class into a controller or service:
public function index(GeneralSettings $settings) {
return view('home', ['site_name' => $settings->site_name]);
}
public function show(GeneralSettings $settings) {
return view('settings', compact('settings'));
}
public function __construct(private GeneralSettings $settings) {}
default_repository in config/settings.php (e.g., database or redis).public static function repository(): ?string {
return 'redis';
}
config/settings.php:
'cache' => [
'enabled' => true,
'store' => 'redis',
'ttl' => 60, // Cache for 60 minutes
],
$settings->save() to invalidate cached values.public function update(GeneralSettingsRequest $request, GeneralSettings $settings) {
$settings->site_name = $request->validated('site_name');
$settings->save();
}
fill() for bulk updates:
$settings->fill($request->validated());
$settings->save();
auth, payment, notifications).
class AuthSettings extends Settings {
public static function group(): string {
return 'auth';
}
}
public string $api_key = env('API_KEY', 'default_key');
Missing Migrations
php artisan migrate after creating/updating migrations.Incorrect Group Names
group() method or migration paths (e.g., general vs General).$this->migrator->exists('general.site_name');
Circular Dependencies
AuthSettings using UserSettings).Type Mismatches
string as an int or vice versa.global_casts or define casts in the settings class:
use Spatie\LaravelSettings\SettingsCasts\Cast;
public int $user_count;
public static function casts(): array {
return [
'user_count' => Cast::asInt(),
];
}
Repository Misconfiguration
default_repository and per-class repository() methods.Check Repository Contents:
$repository = app('settings.repositories.database');
$data = $repository->get('general');
dd($data);
Enable Logging:
Add to config/settings.php:
'debug' => true,
Logs will appear in storage/logs/laravel.log.
Validate Migrations:
Use php artisan settings:list to inspect stored settings:
php artisan settings:list general
Custom Repositories
Spatie\LaravelSettings\SettingsRepositories\SettingsRepository for custom storage (e.g., S3, DynamoDB).Custom Encoders/Decoders
encoder/decoder in config/settings.php for non-JSON storage (e.g., YAML):
'encoder' => function ($value) { return yaml_emit([$value]); },
'decoder' => function ($value) { return yaml_parse($value)[0]; },
Event Listeners
settings.saved or settings.updated events:
Event::listen(SettingsSaved::class, function (SettingsSaved $event) {
Log::info("Settings updated: {$event->settingsClass}");
});
Dynamic Settings
Settings::make() for runtime-created settings (not recommended for production):
$tempSettings = Settings::make('temp', [
'value' => 'dynamic',
]);
'cache' => [
'enabled' => true,
'ttl' => 3600, // 1 hour
],
fill() to minimize database writes:
$settings->fill($request->all());
$settings->save();
env() or vaults like Hashicorp Vault).public function update(Request $request, GeneralSettings $settings) {
$this->authorize('update-settings');
// ...
}
$this->app->bind(
'settings.repositories.database',
fn() => new MockRepository()
);
assertEquals to verify settings:
$settings = app(GeneralSettings::class);
$this->assertEquals('Expected', $settings->site_name);
$this->artisan('migrate:fresh')
->expectsQuestion('Do you really wish to...', 'yes')
->run();
---
How can I help you explore Laravel packages today?