Lightpack Settings
Modern web applications need dynamic, database-driven settings to power everything from feature toggles and branding to user preferences and operational parameters.
Why Database-Driven Settings?
- Instant updates: Change app behavior without code deploys.
- Multi-tenant support: Each user, organization, product, or any model can have their own settings.
- Feature toggles: Enable/disable features on the fly.
- Central management: Manage all settings from an admin UI or API.
- Polymorphic: Settings can be attached to any model, not just users or orgs.
Data Model
settings table
| Column | Type | Notes |
|---|---|---|
| id | int | PK, auto-increment |
| key | string(150) | Setting key (not necessarily unique globally) |
| value | text | Serialized or plain value |
| key_type | string(25) | (optional) for type hints (int, bool, json, etc.) |
| group | string(150) | Logical namespace (e.g., 'global', 'users', etc.) |
| owner | bigint | The owner id within the group (nullable for global) |
| updated_at | timestamp | Last update time |
Indexes:
- Composite index on (
group,owner,key) for efficient lookups.
Migration
Create schema migration file:
php console create:migration --support=settings
Run migration:
php console migrate:up
Configuration
Please run following command to create config/settings.php configuration file.
php console create:config --support=settings
Core API (via Model Trait)
On any model using SettingsTrait:
class User extends Model
{
use Lightpack\Settings\SettingsTrait;
}
$user->settings()->set('key', 'value');
$value = $user->settings()->get('key', 'default');
$all = $user->settings()->all();
$user->settings()->forget('key');
Global/App Settings
Instantiate via container or you can type hint Settings as your controller's method dependency.
app('settings')
->group('global')
->owner(null)
->set('site_name', 'Lightpack Demo');
$name = app('settings')
->group('global')
->owner(null)
->get('site_name', 'Default Name');
Owner/Tenant/Model specific
app('settings')
->group('users')
->owner($userId)
->set('theme', 'dark');
app('settings')
->group('products')
->owner($productId)
->set('tax_rate', 0.18);
Or, better using the trait on the model:
$user = new User(23);
$user->settings()->set('theme', 'dark');
$product = new Product(100);
$product->settings()->set('tax_rate', 0.18);
Design Principles
- Explicit API: No global helpers or magic loading—always opt-in via trait or direct instantiation.
- No Magic: Settings are loaded only when requested, not injected everywhere.
- Type Safety: Values are stored with explicit type hints (
key_type), and serialization/casting is handled explicitly. - Extensible: Add new groups, owners, or custom serialization as needed.
- Cache-Friendly: Caches settings per group/owner scope, with auto-invalidation on update.
- Polymorphic: Any model or logical group can have settings—no schema changes needed for new types.
- Isolation: Always enforce tenant/model ownership before reading/writing settings.
Advanced Features
- JSON/Array Support: Store and retrieve structured data with automatic (de)serialization.
- Caching: Settings are cached per group/owner (using Lightpack's cache system), and cache is invalidated on update/delete for consistency and performance.
- Type Handling: Values are automatically cast to the declared type (
int,bool,float,json, etc.) on retrieval. - Multi-tenant Ready: Use
group/ownerfor per-tenant, per-user, per-product, etc. settings. -
Environment Awareness: Optionally fallback to
.envor config files if not found in DB.