laranail/settings is not published to Packagist, so there is no registry-version badge to show: see Install.
Key-value settings for any Laravel owner (the application, a user, a tenant, a product), stored in layered stores that work even before the database exists, and after it does.
Requires PHP 8.4.1+ or 8.5 and Laravel 13. Works on MySQL, PostgreSQL and SQLite; SQL Server is not supported in 0.x.
Pre-1.0. 0.1.0 is the first tagged release. Before 1.0 a minor release may change the API; Upgrading and the CHANGELOG say what changed.
flowchart LR
php["PHP API: facade, settings(), HasSettings, typed classes"] --> actions
rest["REST API, opt-in"] --> actions
cli["Artisan commands"] --> actions
actions["the same actions: authorize, validate, write, audit"] --> stores
subgraph stores ["Stores, each holding values per owner: the application, a user, a tenant, a product"]
direction LR
database["database layer"] --> runtime["runtime JSON file"] --> shipped["shipped defaults file"]
end
Reads walk a store's layers in order. While the application installs, a store in bootstrap mode
is answered by its files, and promote later moves what was written to them into the database. Architecture
has the read and write paths and the tables.
composer require laranail/settingslaranail/* packages resolve from their GitHub repositories, not Packagist; see
Installation for the repositories entries.
Publish the config and the package's one migration (it creates settings_categories, a values
table per database store, settings_audit, settings_history, settings_change_requests,
settings_definitions and settings_stores), migrate, and optionally seed the default categories.
The default store reads the database first, then its runtime file, then shipped defaults from
settings/defaults.php when that file exists.
php artisan laranail::settings.install
php artisan migrate
php artisan db:seed # general, appearance, localisation, mail, notifications, securityFor multi-tenant applications set tenancy.mode before migrating (see
Tenancy). To keep values per owner, list the owner's morph alias in a
store's owners (for example 'owners' => ['user'] under stores.settings); an alias no store
lists raises OwnerNotAllowed.
An application without a database drops database from stores.settings.layers and keeps its
values in storage/app/private/laranail/settings/settings.json.
use Simtabi\Laranail\Settings\Facades\Settings;
Settings::set('site.name', 'Acme');
Settings::get('site.name'); // 'Acme'
Settings::get('site.tagline', 'Welcome'); // the default when nothing is stored
Settings::many(['site.name', 'site.tagline' => 'Welcome']);
Settings::all('mail'); // every visible key under mail.// Per owner, in the store that accepts its alias, falling back to parents when allowed.
Settings::for($user)->set('ui.theme', 'dark');
Settings::for($user)->get('ui.theme', 'light');// On a user's behalf: checked against the laranail-settings.* gates and audited.
Settings::as($user)->because('INC-123')->set('mail.from.address', 'ap@acme.test');// A typed class over the same keys (loaded and saved through the same write actions).
$mail = MailSettings::load(Settings::as($user));
$mail->fromAddress = 'ops@acme.test';
$mail->save();The JSON REST API is off until http.enabled is true; the REST API quick start
gets a first request through. When something does not resolve as expected, run
php artisan laranail::settings.doctor and see Troubleshooting.
Getting started walks through stores, owners and definitions; the Documentation index lists every page.
The hosted docs live at https://opensource.simtabi.com/documentation/laranail/settings/.
- Installation — Composer repositories, requirements and the install command.
- Getting started — stores, owners and definitions in a first application.
- Configuration — every key in
config/laranail/settings.php. - Architecture — stores, layers, owners, categories and why they are shaped this way.
- Troubleshooting — the common errors, what causes them, and
doctorandshow. - Upgrading — where changes are recorded, and the steps after an upgrade.
- Release — versioning, tags and how a release is cut.
- Settings API — every method of the handle, the facade, the
settings()helper,HasSettingsand typed settings, with examples, exceptions and events. - Exceptions — every exception, when it is raised and how the REST API answers it.
- Definitions — types, defaults, rules, encryption, locks and precedence.
- Drivers and layers — the built-in drivers and custom ones.
- Database — the tables, version-checked writes, eager loading and
HasSettings. - Categories — nested, per-store categories and the rules that guard them.
- Commands — install, make-store, promote, doctor, show, sync-definitions, warm, clear-cache, history, export, import, diff, reencrypt, rescope and the prune commands.
- Owners and inheritance — owner references, store routing and the cascade.
- Access control — actors, abilities, authorizers, guarded locks, sensitive reads and step-up verification.
- Audit and logging — the audit trail, its sinks and the operational log.
- Runtime configuration — stores, definitions and access changed in code for one request.
- Runtime overrides — a value held in memory for one request or job, ahead of every stored layer; never written, cached or audited.
- Audit queries — reading the audit trail from PHP, gated by
view_audit. - Tenancy — tenant column or database per tenant, the discriminator, and the stancl and spatie adapters.
- Models and factories — Eloquent models and factories for tests, seeding and admin screens.
- Caching — per-scope bags, tenant-safe keys, generation tokens and stale-while-revalidate.
- History — every value by version, rollback and diffs, and retention.
- Events — every event, when it is dispatched, and the built-in listeners.
- Alerts — notifications on changes and refusals, by rule, throttled, never with a value.
- Approvals — four-eyes change requests: proposing, approving, stale and expired requests.
- Import and export — portable JSON documents, secrets modes, dry runs and store diffs.
- Importers — moving in from spatie/laravel-settings, toolkit's JSON store and akaunting/laravel-setting.
- Re-encryption and rescoping — after an
APP_KEYrotation, and after renaming a morph alias. - Persisted configuration — stores, layers and definitions kept in the database.
- REST API — the opt-in JSON API: endpoints, ETags, approvals, problem details and idempotency.
- REST API reference — every route: ability, request, response, status codes and problem types.
- Typed settings — typed classes over the key-value engine, and settings migrations.
- Ship defaults with the application — a versioned defaults file instead of
.env. - Test code that uses settings —
Settings::fake()and its assertions. - Override a setting for one request — middleware, a queued job and a feature switch, with nothing written.
- Act as a user — authorize and audit changes made on a user's behalf.
- Move from files to the database — bootstrap mode during install, then promotion.
- Seed the default categories — the shipped set, your own set, and per tenant.
- Warm the cache after a deploy — warm, and reset after changing rows by hand.
- Roll back a setting — find a version, compare it, return to it.
- Listen to settings events — your own listeners, and reading the new value.
- Approve a change — require a second person, then review and apply.
- REST API quick start — enable the API, authenticate and make a first request.
- Call the REST API with Sanctum — a token with an ability ceiling, ETags and idempotency.
- Migrate from spatie/laravel-settings — import the values and keep typed classes.
- Migrate from laranail/toolkit's settings store — import toolkit's JSON file from a local path or a disk.
- Build your own admin UI on the REST API — forms from definitions, ETag saves, history and activity.
- Read settings from an SPA or a mobile app — cookies or tokens, ETags and safe retries.
- Build a per-user preferences screen — defaults,
many(),setMany()and resetting. - Set up multi-tenancy — a tenant column or a database per tenant.
- Audit a change — who, when, why, and the value before.
- Move settings between environments — export, diff and a dry-run import.
- Use typed settings — a typed class over a group of keys.
See CONTRIBUTING.md (composer test runs the suite) and
SECURITY.md for reporting vulnerabilities.
MIT. See LICENSE.