# DB Config - Filament Database Settings Manager ## Introduction DB Config is a lightweight Filament plugin that provides a database-backed key/value store for managing application settings and editable content in Laravel applications. The package eliminates the need for custom Eloquent models or complex configuration classes, storing all data as JSON in a single database table with transparent caching. It's designed for both traditional configuration values (site name, contact info, maintenance mode) and dynamic page content (homepage sections, landing page blocks, about text). The plugin seamlessly integrates with Filament's form system, supporting any form field component including third-party ones. It provides a command-line generator to scaffold settings pages, simple helper functions for reading and writing values, and a Blade directive for template access. All data is cached automatically with configurable TTL, and cache invalidation happens transparently when values are updated. The package requires no external dependencies beyond Filament and Laravel, making it a minimal-footprint solution for runtime-editable settings. ## Installation ```bash # Install via Composer composer require inerba/filament-db-config # Publish migration php artisan vendor:publish --tag="db-config-migrations" # Run migration to create db_config table php artisan migrate # Optional: Publish configuration file php artisan vendor:publish --tag="db-config-config" ``` ## Configuration File ```php 'db_config', // Cache settings 'cache' => [ 'prefix' => 'db-config', // Cache key prefix 'ttl' => null, // null = cache forever, or set minutes ], ]; ``` ## Generate Settings Pages ```bash # Interactive mode (prompts for name and panel) php artisan make:db-config # With arguments: create WebsiteSettings page in default panel php artisan make:db-config Website # Specify panel: create WebsiteSettings page in Admin panel php artisan make:db-config Website Admin ``` ## Reading Configuration Values - Helper Function ```php set('website.contact', [ 'email' => 'info@example.com', 'phone' => '+1234567890', 'address' => ['city' => 'New York', 'zip' => '10001'] ]); $email = db_config('website.contact.email', 'default@example.com'); // Returns: 'info@example.com' $city = db_config('website.contact.address.city', 'Unknown'); // Returns: 'New York' $country = db_config('website.contact.address.country', 'USA'); // Returns: 'USA' (default, since 'country' doesn't exist) ``` ## Reading Configuration Values - Static Class Method ```php 'Acme Inc.', 'contact_email' => 'info@acme.test', ...] // Get last updated timestamp for a group $lastUpdate = DbConfig::getGroupLastUpdatedAt('website', 'F j, Y, g:i a', 'America/New_York'); // Returns: 'October 23, 2025, 3:45 pm' or null if not found ``` ## Reading Configuration Values - Facade ```php {{ db_config('website.site_name', 'My Site') }} {{-- Using Blade directive --}} @db_config('website.site_name', 'Default Title') {{-- Maintenance mode check --}} @if(db_config('website.maintenance_mode', false))
Site is under maintenance
@endif ``` ## Writing Configuration Values ```php 'dark', 'language' => 'en', 'notifications' => [ 'email' => true, 'sms' => false, 'push' => true ] ]); // Set boolean value DbConfig::set('website.maintenance_mode', true); // Set array value DbConfig::set('website.social_links', [ 'twitter' => 'https://twitter.com/example', 'facebook' => 'https://facebook.com/example', 'linkedin' => 'https://linkedin.com/company/example' ]); // Cache is automatically invalidated when setting values DbConfig::set('website.site_name', 'New Name'); $name = DbConfig::get('website.site_name'); // Fresh value from DB ``` ## Creating Custom Settings Page ```php 'My Application', 'posts_per_page' => 10, 'allow_comments' => true, 'maintenance_mode' => false, ]; } // Define the form schema public function content(Schema $schema): Schema { return $schema ->components([ Section::make('General Settings') ->schema([ TextInput::make('site_name') ->label('Site Name') ->required() ->maxLength(255), TextInput::make('contact_email') ->label('Contact Email') ->email() ->required(), Textarea::make('site_description') ->label('Site Description') ->rows(3) ->maxLength(500), ]), Section::make('Features') ->schema([ Toggle::make('maintenance_mode') ->label('Maintenance Mode') ->helperText('Enable to show maintenance page to visitors'), Toggle::make('allow_comments') ->label('Allow Comments') ->default(true), TextInput::make('posts_per_page') ->label('Posts Per Page') ->numeric() ->minValue(1) ->maxValue(100) ->default(10), ]), ]) ->statePath('data'); // Required for proper state binding } } ``` ## Advanced Settings Page with Nested Data ```php 'Welcome to Our Website', 'hero_subtitle' => 'We provide amazing services', 'features' => [], ]; } public function content(Schema $schema): Schema { return $schema ->components([ TextInput::make('hero_title') ->label('Hero Title') ->required() ->maxLength(100), TextInput::make('hero_subtitle') ->label('Hero Subtitle') ->maxLength(200), RichEditor::make('hero_description') ->label('Hero Description') ->toolbarButtons(['bold', 'italic', 'link']), FileUpload::make('hero_image') ->label('Hero Background Image') ->image() ->maxSize(2048), Repeater::make('features') ->label('Features') ->schema([ TextInput::make('title')->required(), Textarea::make('description')->rows(2), TextInput::make('icon')->label('Icon Class'), ]) ->collapsible() ->defaultItems(0), ]) ->statePath('data'); } } ``` ## Using Settings in Controllers ```php $siteName, 'heroTitle' => $homepage['hero_title'] ?? 'Welcome', 'heroSubtitle' => $homepage['hero_subtitle'] ?? '', 'features' => $homepage['features'] ?? [], ]); } } ``` ## Database Schema ```php id(); // Primary key $table->string('group'); // Group name (e.g., 'website') $table->string('key'); // Setting key (e.g., 'site_name') $table->json('settings')->nullable(); // JSON value storage $table->unique(['group', 'key']); // Unique constraint $table->timestamps(); // created_at, updated_at }); // Example data: // | id | group | key | settings | created_at | updated_at | // |----|----------|------------|-------------------------------|------------|------------| // | 1 | website | site_name | "Acme Corp" | ... | ... | // | 2 | website | contact | {"email":"info@acme.test"} | ... | ... | // | 3 | homepage | hero_title | "Welcome to Our Website" | ... | ... | ``` ## Testing with DB Config ```php assertEquals('Hello World', $value); } public function test_nested_values_work() { DbConfig::set('test.nested', [ 'level1' => [ 'level2' => 'deep value' ] ]); $value = DbConfig::get('test.nested.level1.level2'); $this->assertEquals('deep value', $value); } public function test_default_values_returned() { $value = DbConfig::get('nonexistent.key', 'default'); $this->assertEquals('default', $value); } public function test_get_group_returns_all_settings() { DbConfig::set('test.key1', 'value1'); DbConfig::set('test.key2', 'value2'); $group = DbConfig::getGroup('test'); $this->assertIsArray($group); $this->assertEquals('value1', $group['key1']); $this->assertEquals('value2', $group['key2']); } } ``` ## Custom Cache Configuration ```php 'app_settings', // Custom table name 'cache' => [ 'prefix' => 'my-app-settings', // Custom cache prefix 'ttl' => 60, // Cache for 60 minutes instead of forever ], ]; // Clear cache manually if needed use Illuminate\Support\Facades\Cache; // Clear specific setting Cache::forget('my-app-settings.website.site_name'); // Clear all cache (including DB Config cache) php artisan cache:clear ``` ## Summary DB Config is a practical solution for Laravel/Filament applications that need runtime-editable settings without the complexity of dedicated settings classes or custom models. It excels at managing both traditional application configuration (API keys that shouldn't be in .env, feature flags, display preferences) and dynamic content sections (homepage heroes, about page text, FAQ entries). The package follows the principle of convention over configuration, requiring minimal setup while providing maximum flexibility through Filament's form system. The two-tier key structure (group.setting with optional nested paths) organizes settings logically while the transparent caching layer ensures excellent performance. Pages extending AbstractPageSettings inherit all CRUD functionality automatically, leaving developers to focus only on defining form fields. The package is ideal for small to medium applications, admin panels, marketing sites, or any project where non-technical users need to edit content without touching code. For applications requiring strict typing, DTOs, and validation logic tightly coupled to domain models, consider Spatie Laravel Settings instead.