javaabu/settings
A flexible settings package for Laravel that stores configurable key-value options in the database, with caching and a simple API for reading and updating application settings at runtime via facade or helper functions.
v1.0.0 is the first stable tag, so treat it as a fresh baseline rather than an upgrade. The release notes contain only a changelog link, so verify behaviour against the README and the published config rather than assuming prior-version parity.
composer require javaabu/settings
php artisan vendor:publish --provider="Javaabu\Settings\SettingsServiceProvider"
php artisan migrate
config/settings.php. This is the source of truth — it defines the setting keys, defaults, types, validation rules and grouping used by the admin form and by the read helpers. Read it before reading any other source.Setting model, the settings service/repository and the settings() helper live under vendor/javaabu/settings/src.setting('site.name'); // with default from config
setting('site.name', 'My App'); // explicit fallback
settings()->all(); // collection/array of everything
First use case: replace hard-coded site identity and toggles (site name, support email, maintenance mode, feature flags) with a single admin-editable settings page, so non-developers can change them without a deploy.
Config-driven definitions. Declare each setting once, with its type, default and validation, then let the package render and persist it:
// config/settings.php
return [
'site.name' => [
'type' => 'text',
'default' => config('app.name'),
'rules' => ['required', 'string', 'max:255'],
'group' => 'general',
],
'site.maintenance' => [
'type' => 'boolean',
'default' => false,
'group' => 'general',
],
];
The same array drives the admin form, the validation on save, and the default returned by setting() — keep it as the only place these values are declared.
Read path in application code. Call the helper or facade directly at the point of use rather than copying values into your own config; the package caches reads, so this is cheap:
if (setting('site.maintenance')) {
// ...
}
For Blade, {{ setting('site.name') }} is fine. For values used in many requests, resolve once in a view composer or middleware rather than in every partial.
Write path. Prefer the package's own setter/form flow so validation and cache invalidation run:
settings()->set('site.name', $request->input('site_name'));
Build the admin screen by iterating the config groups and rendering an input per type (text, textarea, boolean, select, file). Posting to the package controller gives you validation for free; a hand-rolled controller means you must re-apply the rules yourself.
Boolean and select handling. HTML checkboxes post nothing when unchecked — normalise to false before saving, otherwise you will write null and the config default resurfaces.
Feature flags and progressive rollout. Settings are a lightweight alternative to env vars for runtime toggles; keying them as features.* with boolean type keeps them grouped and visible in the same admin screen.
Testing. Reset between tests, since the cached store persists across a test class:
protected function setUp(): void
{
parent::setUp();
// flush the package cache and re-seed any settings your test asserts on
}
Use the array cache driver in phpunit.xml so tests do not leak into your local Redis.
Seeding and deploy. Provide a seeder that writes defaults for keys your code assumes exist, so a fresh environment is not dependent on someone visiting the admin page. Run it in your deploy pipeline after migrate.
settings table with SQL or a seeder bypasses the invalidation. Always go through the setter, or explicitly clear the cache afterwards. "I changed it but the app still shows the old value" is the number one symptom with this package.null vs default. A stored null and an absent key can behave differently depending on the lookup. Treat an empty string from a form as "reset to default" deliberately, or you will store empty values that shadow your config defaults.Setting::create()/update() from a script or seeder skips the configured rules. If data integrity matters, validate in the seeder too.config:cache in production. Your config/settings.php is cached. After changing definitions, you must re-run php artisan config:cache (and clear the settings cache) as part of deploy — otherwise new keys silently never appear."false" is truthy in PHP.php artisan storage:link plus a correctly configured disk; the DB stores the path, so changing disks later orphans existing values.tenant.{id}.site.name) or bind a custom model/repository through the container rather than forking the package.settings table, rename or namespace before installing — the published migration will collide.app/ and re-publish on major upgrades.php artisan tinker → setting('your.key') tells you what the app actually resolves; compare against DB::table('settings')->where('key', '...')->first() to see whether the problem is storage or cache."javaabu/settings": "^1.0") and re-read these notes on each minor bump; pre-1.0 users should diff their published config and views against the new stubs before upgrading, as no migration guide is provided in the release notes.How can I help you explore Laravel packages today?