paulohps/laravel-db-config

Override Laravel config values at runtime with values stored in the database.

Maintainers

Package info

github.com/paulohps/laravel-db-config

pkg:composer/paulohps/laravel-db-config

Transparency log

Statistics

Installs: 2

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v1.1.1 2026-07-29 15:05 UTC

This package is auto-updated.

Last update: 2026-07-29 15:05:50 UTC


README

Override Laravel config values at runtime with values stored in the database.

You decide, per config file, which keys may be overridden — either by allowing only a few keys (only) or by allowing everything except a few keys (except). The service provider reads the stored values on boot and applies the allowed ones on top of the file-based configuration.

Requires PHP 8.4+ and Laravel 12+.

Installation

composer require paulohps/laravel-db-config
php artisan migrate

The migration for the db_config_settings table is loaded automatically. Publishing the config file (and optionally the migration) is available via:

php artisan vendor:publish --tag=db-config-config
php artisan vendor:publish --tag=db-config-migrations

Configuration

// config/db-config.php
return [
    // Turn the runtime overriding on/off. When off, nothing is overridden
    // and the app falls back to the plain file-based configuration.
    'enabled' => env('DB_CONFIG_ENABLED', true),

    'table' => 'db_config_settings',
    'connection' => null,

    // Cache the stored settings so the provider does not query the database
    // on every request. 'store' = cache store (null = default), 'ttl' in
    // seconds (null = forever).
    'cache' => [
        'enabled' => env('DB_CONFIG_CACHE_ENABLED', true),
        'store' => env('DB_CONFIG_CACHE_STORE'),
        'key' => 'db-config',
        'ttl' => null,
    ],

    // Which config files (and keys) may be overridden from the database.
    'configs' => [
        '*',                                           // every file
        'app',                                         // every key of app.php
        'mail' => ['only' => ['from.address', 'from.name']],
        'services' => ['except' => ['ses.secret']],
    ],
];

Rules:

  • '*' allows every file. Files with an explicit entry keep their own rules even when '*' is present.
  • only: only the listed keys of that file may be overridden.
  • except: every key of that file may be overridden, except the listed ones — useful when excluding a few keys is shorter than listing all the others.
  • Keys match by dot-notation prefix: from also covers from.address.
  • With except, ancestors of an excluded key are blocked too (overriding from could smuggle a value into the excluded from.address), and whole-file overrides are never allowed when key rules exist.
  • When both only and except are given for the same file, only wins.

Usage

Stored keys are full config keys in dot notation (config file name first). Values that do not pass the rules above are ignored at apply time.

use Paulohps\DbConfig\Facades\DbConfig;

// Persist a value and apply it immediately (throws KeyNotConfigurableException
// when the key is not allowed by the rules):
DbConfig::set('mail.from.address', 'hello@myapp.com');

// Read the stored (database) value, ignoring the file config:
DbConfig::get('mail.from.address');          // 'hello@myapp.com'
DbConfig::get('mail.from.name', 'fallback'); // 'fallback' (never stored)

// Remove the override — the file value is restored on the next request:
DbConfig::forget('mail.from.address');

// Check whether a key may be overridden:
DbConfig::allows('mail.from.address'); // bool

Values are JSON-encoded, so arrays, booleans, numbers and null round-trip.

Caching

With cache.enabled on (the default), the stored settings are cached — forever when ttl is null, otherwise for ttl seconds — and the database is only queried again after the cache is invalidated.

Every write that goes through the Eloquent model — set(), forget(), a seeder or admin panel calling create()/update()/delete() on DbConfigSetting — rebuilds the cache automatically. The observer handles events after the transaction commits, so a rolled-back write never poisons the cache. Writes that bypass model events (query-builder update(), DB::table(), raw SQL) do not trigger the rebuild; after those, flush by hand:

DbConfig::flushCache();   // next read repopulates
// or
DbConfig::refreshCache(); // flush and repopulate right away

On multi-server setups use a shared store (Redis, Memcached, database) so the invalidation reaches every server; with a per-server store (file, array) the other servers keep the stale payload until their ttl expires.

Caveats

  • config:cache: the overrides are applied at runtime on every request, on top of the (possibly cached) file config. With the settings cache disabled this costs one database query per request.
  • Boot order: providers that read config in register(), or that boot before this package's provider, see the file value instead of the database value.
  • Resilience: when the database is unavailable or not migrated yet (fresh install, CI), the provider silently skips the overrides instead of taking the application down.

Testing

composer test      # Pest
composer analyse   # PHPStan (level 8, via Larastan)
composer format    # Pint

License

MIT. See LICENSE.md.