Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Dynamic Configuration Bundle Laravel Package

oneguard/dynamic-configuration-bundle

OneGuard Dynamic Configuration Bundle provides runtime configuration management for Symfony applications, letting settings be defined, overridden, and persisted without code changes. Ideal for feature flags, environment-specific values, and admin-editable options.

View on GitHub
Deep Wiki
Context7

Getting Started

  • Read the compatibility surface before installing. This is a Symfony bundle: its composer.json will pull symfony/framework-bundle (and almost certainly Doctrine). Laravel does not have a bundle kernel, so composer require oneguard/dynamic-configuration-bundle gives you the code but no wiring — there is no config/app.php entry to add and no bundles.php to register it in. The package is also archived, with 1 star and 0 dependents, so treat it as a reference implementation rather than a dependency.
  • Where to look first, if you open the repo:
    1. README.md — the expected table schema/settings keys.
    2. DependencyInjection/*Extension.php — how config is read and which parameters are set.
    3. Resources/config/services.* — the repository/service that actually queries the database.
    4. The entity/repository — the table shape and value typing.
  • First use case in a Laravel app: replicate the pattern (DB-backed settings merged into runtime config) with Laravel primitives. A minimal port looks like:
// migration
Schema::create('settings', function (Blueprint $t) {
    $t->string('key')->primary();
    $t->text('value')->nullable();
    $t->string('type')->default('string'); // string|int|bool|json
    $t->timestamps();
});
class SettingsRepository
{
    public function __construct(private Cache $cache, private Connection $db) {}

    public function all(): array
    {
        return $this->cache->rememberForever('settings.all', function () {
            return $this->db->table('settings')->get()
                ->mapWithKeys(fn ($r) => [$r->key => $this->cast($r)])
                ->all();
        });
    }

    public function flush(): void { $this->cache->forget('settings.all'); }

    private function cast(object $row): mixed
    {
        return match ($row->type) {
            'int'   => (int) $row->value,
            'bool'  => filter_var($row->value, FILTER_VALIDATE_BOOL),
            'json'  => json_decode($row->value, true),
            default => $row->value,
        };
    }
}
class SettingsServiceProvider extends ServiceProvider
{
    public function register(): void
    {
        $this->app->singleton(SettingsRepository::class);
    }

    public function boot(): void
    {
        try {
            if (Schema::hasTable('settings')) {
                config(['settings' => app(SettingsRepository::class)->all()]);
            }
        } catch (\Throwable) {
            // fresh install / DB unavailable — skip
        }
    }
}

That mirrors what the bundle does (read rows → deserialize → merge into a parameter bag) using Laravel’s config repository and cache.

Implementation Patterns

  • Port the strategy, not the code. The bundle’s core is: repository reads rows → value transformer by type → merge into Symfony’s parameter bag. In Laravel the equivalents are a singleton repository, match-based casting, and config(['settings' => ...]) (or a dedicated dynamic namespace so it doesn’t collide with app.*).
  • Cache-first repository, busted by model events. Wrap reads in Cache::rememberForever and clear on saved/deleted via an observer. This reproduces the bundle’s cache-warmup concept without touching the config cache.
  • Prefer lazy resolution over boot-time hydration for hot paths (health checks, queue workers, Octane). Bind a memoized singleton and merge into config on first access rather than in boot(), so a cold DB doesn’t fail the whole app.
  • Keep a clean boundary. Copy the bundle’s repository interface if it exposes one, and bind your own implementation in a service provider — that’s the same extension point, expressed idiomatically in Laravel.
  • Symfony → Laravel translation table if you’re reading the bundle alongside:
    Symfony bundle concept Laravel equivalent
    Bundle Extension / prependExtension ServiceProvider register() + mergeConfigFrom()
    Compiler pass $this->app->extend() / contextual binding
    Parameter bag config() repository
    Cache warmer Cache::remember + observer flush
  • If you genuinely need the bundle (e.g. inside an adjacent Symfony service), don’t cross-wire containers. Let the Symfony app own the bundle and expose effective config to Laravel via HTTP, queue, or Redis — or just read the same table from both.
  • Admin write path: add a Settings::set() that writes the row, casts by type, flushes the cache, and optionally calls a reload() on the repository singleton. This is the one place to centralize all invalidation.

Gotchas and Tips

  • Archived and unmaintained: no Laravel support, no security patches, Doctrine-coupled. If you must vendor it, pin a commit and audit the transitive deps.
  • php artisan config:cache will bite you. Files in config/ are evaluated during warmup — never query the DB from inside a config file (the DB may not exist yet, and the values get frozen into the cached config). Load dynamic settings at boot or lazily, not in config/*.php.
  • Every-request queries: provider boot() runs on every request. Guard Schema::hasTable('settings') with a cached boolean, and always memoize repository reads. On Octane, that guard result and the singleton both persist across requests.
  • Octane and long-running workers: boot-time config and singletons survive between requests. Settings changes won’t appear until php artisan octane:reload (or a worker restart). If changes must be live, read the cached repository per request instead of snapshotting into config().
  • Migrations / seeders / fresh installs: boot() runs before the settings table exists. Wrap in try/catch and short-circuit; don’t let a missing table take down php artisan migrate or an empty CI database.
  • Testing: add a null/array driver toggled by env in phpunit.xml, use RefreshDatabase, and assert on the repository return value — not on global config() mutation, which leaks between tests.
  • Porting quirks from the bundle: config resolution order (bundle config < parameters < env), needing cache:clear after changes, and kernel boot ordering. Copy the typed value transformer (string|int|bool|json) and the cache key/version — those are the genuinely reusable bits.
  • Don’t try to “register” the bundle in Laravel. There is no bundle kernel; any claim that it “just works” means someone wrote an adapter — verify before depending on it.
  • Extension points worth preserving in your port: the repository interface (swap drivers for tests), a flush()/reload() method for the settings-save flow, and a type-cast strategy so adding float, datetime, or array values is a one-line change rather than a schema migration.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle
glavweb/extra-bundle
glavweb/api-bundle
glavweb/admin-bundle