A professional Laravel package to store and manage application settings dynamically using the database instead of config files. Supports automatic caching, multi-tenant scoping, per-user overrides, and a beautiful admin panel UI.
- 📦 Database-driven settings — store any key/value with type casting
- ⚡ Automatic caching — configurable driver and TTL, cache invalidated on update
- 🏢 Multi-tenant support — tenant-scoped settings with global fallback
- 👤 Per-user overrides — priority: user → tenant → global
- 🎨 Admin Panel UI — dark-mode Bootstrap 5 CRUD interface with search, filter, toggles
- 🔄 Inline editing — AJAX quick-update widget on the edit page
- 🛡️ Type support —
string,integer,float,boolean,json - 🖥️ Artisan commands —
settings:cache,settings:clear,settings:seed - ✅ Fully tested — PHPUnit test suite included
- PHP 8.1+
- Laravel 10.x / 11.x / 12.x
composer require codersandip/laravel-dynamic-settingsLaravel auto-discovers the service provider. No manual registration needed.
Publish everything at once:
php artisan vendor:publish --tag=settings-allOr selectively:
# Config only
php artisan vendor:publish --tag=settings-config
# Migrations only
php artisan vendor:publish --tag=settings-migrations
# Views only
php artisan vendor:publish --tag=settings-views
# Routes only
php artisan vendor:publish --tag=settings-routesphp artisan migratephp artisan settings:seedAfter publishing, edit config/settings.php:
return [
// Cache driver (file, redis, memcached, array)
'cache_driver' => env('SETTINGS_CACHE_DRIVER', 'file'),
// Cache TTL in seconds (3600 = 1 hour)
'cache_ttl' => env('SETTINGS_CACHE_TTL', 3600),
// Cache key prefix
'cache_prefix' => env('SETTINGS_CACHE_PREFIX', 'dyn_setting'),
// Admin panel URL prefix
'route_prefix' => env('SETTINGS_ROUTE_PREFIX', 'admin/settings'),
// Middleware applied to admin routes
'route_middleware' => ['web', 'auth'],
// Available groups in the dropdown
'groups' => ['general', 'email', 'payment', 'security'],
];You can also set these in your .env file:
SETTINGS_CACHE_DRIVER=redis
SETTINGS_CACHE_TTL=7200
SETTINGS_ROUTE_PREFIX=dashboard/settings// Get a setting
setting('site_name'); // → 'My Application'
// Get with a default value
setting('site_name', 'Default App'); // → 'Default App' if not set
// Get with tenant context (falls back to global if not found)
setting('currency', 'USD', $tenantId);
// Get with tenant + user context
setting('theme', 'light', $tenantId, $userId);// Via helper (chained)
setting()->set('site_name', 'My App');
// With options
setting()->set('page_size', 20, [
'type' => 'integer',
'group' => 'general',
'description' => 'Results per page',
]);use Codersandip\DynamicSettings\Facades\Settings;
Settings::get('site_name');
Settings::get('site_name', 'Default');
Settings::set('site_name', 'New Name');
Settings::delete('site_name');
Settings::has('site_name');use Codersandip\DynamicSettings\Services\SettingsService;
class MyController extends Controller
{
public function __construct(private SettingsService $settings) {}
public function index()
{
$siteName = $this->settings->get('site_name', 'My App');
// ...
}
}| Type | PHP Type | Storage | Example |
|---|---|---|---|
string |
string |
As-is | "Hello World" |
integer |
int |
Numeric string | 42 |
float |
float |
Numeric string | 3.14 |
boolean |
bool |
"1" / "0" |
true / false |
json |
array |
JSON string | ["stripe", "paypal"] |
setting()->set('enabled', true, ['type' => 'boolean']);
setting()->set('count', 100, ['type' => 'integer']);
setting()->set('gateways', ['stripe', 'pp'], ['type' => 'json']);
setting('enabled'); // → true (bool)
setting('count'); // → 100 (int)
setting('gateways'); // → ['stripe', 'pp'] (array)Settings resolve with this priority: user → tenant → global
// Store global setting
setting()->set('currency', 'USD');
// Store tenant-specific override
setting()->set('currency', 'GBP', ['tenant_id' => 5]);
// Store user-specific override (within a tenant)
setting()->set('currency', 'EUR', ['tenant_id' => 5, 'user_id' => 12]);
// Retrieval
setting('currency'); // → 'USD' (global)
setting('currency', null, 5); // → 'GBP' (tenant 5 override)
setting('currency', null, 5, 12);// → 'EUR' (user 12 override)
setting('currency', null, 5, 99);// → 'GBP' (user 99 falls back to tenant)
setting('currency', null, 9); // → 'USD' (tenant 9 falls back to global)use Codersandip\DynamicSettings\Facades\Settings;
// Set tenant context once
$tenantSettings = Settings::forTenant(5);
$tenantSettings->get('currency'); // uses tenant 5
$tenantSettings->get('locale');
// Chain tenant + user
Settings::forTenant(5)->forUser(12)->get('theme');| Command | Description |
|---|---|
settings:cache |
Pre-warm cache with all settings from DB |
settings:clear |
Flush the settings cache |
settings:seed |
Seed a set of default settings |
php artisan settings:cache
php artisan settings:clear
php artisan settings:seed
php artisan settings:seed --force # overwrite existing settingsAccess the admin panel at /admin/settings (configurable via route_prefix).
The panel includes:
- 📋 Index — list all settings with search, group/type filter, boolean toggles
- ➕ Create — add a new setting with type, group, scope options
- ✏️ Edit — update a setting, with inline AJAX quick-update widget
- 🗑️ Delete — remove a setting (with confirmation)
Set the middleware in config/settings.php:
'route_middleware' => ['web', 'auth', 'can:manage-settings'],Or disable the built-in routes and define your own:
// config/settings.php
'disable_routes' => true,Then publish routes:
php artisan vendor:publish --tag=settings-routesAnd register the file in bootstrap/app.php or routes/web.php.
settings
├── id (bigint, auto-increment)
├── key (varchar 191, indexed)
├── value (longtext, nullable)
├── type (varchar 20 — string|integer|float|boolean|json)
├── group (varchar 50, indexed, default: general)
├── tenant_id (bigint unsigned, nullable, indexed)
├── user_id (bigint unsigned, nullable, indexed)
├── description (varchar, nullable)
├── is_public (boolean, default: false)
├── created_at
└── updated_at
UNIQUE (key, tenant_id, user_id)
composer testSee CHANGELOG.md.
The MIT License (MIT). See LICENSE for details.
Sandip — contact@codersandip.com
GitHub: github.com/codersandip