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

Database Config Bundle Laravel Package

unifik/database-config-bundle

Unifik DatabaseConfigBundle is a Symfony bundle for storing and managing application configuration in the database instead of flat files. It provides config entities, services, and admin-friendly editing for dynamic, environment-aware settings.

View on GitHub
Deep Wiki
Context7

Getting Started

  1. Install with Composer and register the bundle in your kernel/bundles file:

    composer require unifik/database-config-bundle
    
    // config/bundles.php (Symfony 4+) — or AppKernel::registerBundles() on legacy apps
    return [
        // ...
        Unifik\DatabaseConfigBundle\UnifikDatabaseConfigBundle::class => ['all' => true],
    ];
    
  2. Create the config table. The bundle ships a Doctrine entity (typically Config with name/value columns). Run migrations or, for a quick local start:

    bin/console doctrine:schema:update --force
    

    In production always generate a migration instead of --force.

  3. Seed a couple of rows so you have something to read before wiring up an admin UI:

    bin/console doctrine:query:sql "INSERT INTO config (name, value) VALUES ('site.title', 'My App')"
    
  4. Look here first when exploring the bundle:

    • Entity/Config.php — the persisted shape (column names, types, length limits).
    • Resources/config/services.yml — the service IDs/aliases; confirm the exact manager alias with bin/console debug:container | grep -i config.
    • DependencyInjection/ — how/if values are pushed into container parameters and whether a prefix is applied.
    • README.md — the canonical service name and any required bundle-level config: options.
  5. First real use case: inject the config manager into a service or controller and read a value with a fallback, then write one back from an admin action:

    $title = $this->configManager->get('site.title', 'Default Title');
    $this->configManager->set('site.title', 'New Title');
    

Implementation Patterns

Wrap it in your own Settings service. Don't let the bundle's manager leak across the codebase. A thin application service gives you typing, validation, and a single place to add caching:

final class Settings
{
    public function __construct(private ConfigManager $config, private CacheItemPoolInterface $cache) {}

    public function get(string $key, mixed $default = null): mixed
    {
        $item = $this->cache->getItem('settings.'.$key);
        if (!$item->isHit()) {
            $item->set($this->config->get($key, $default));
            $this->cache->save($item);
        }
        return $item->get();
    }
}

Store structured values as JSON, not ad-hoc strings. For arrays/objects, json_encode on write and json_decode(..., true) on read inside your wrapper. This keeps the value column simple and avoids inventing your own serialization format.

Use it for runtime-editable settings, not container topology. Good fits: site title, feature flags, mail-from address, pagination size, third-party API toggles. Poor fits: service definitions, routing, security roles — those belong in YAML/compiled config.

Admin CRUD pattern. Expose the Config entity through a simple form (name + value, optionally a "type" field) behind ROLE_ADMIN. On save, flush the entity, then invalidate the corresponding cache key and — if the bundle pushes parameters at boot — clear the Symfony cache in non-prod.

Idempotent seeding. Rather than relying on fixtures, add a console command that inserts missing keys only if absent. Run it during deployment so new code can assume defaults exist. Never overwrite operator-changed values.

Layer precedence explicitly. A common pattern is DB value ?? parameters.yml value ?? hard-coded default. Implement the fallback chain in your wrapper so callers express intent once, and document the order so nobody hunts for where a value came from.

Twig convenience. Register a small Twig extension exposing setting('site.title') that delegates to your Settings service, so templates don't inject the raw manager.

Environment separation. If the same database is shared across stages, prefix keys (prod., staging.) or use a separate table/database per env; otherwise a staging tweak silently changes production behavior.

Gotchas and Tips

  • Per-request database reads are the main performance risk. If the bundle loads all rows on every kernel boot, you pay a query on every request. Cache the full set in a warmup command, a PSR-6 pool, or an in-memory map populated once per request. Watch the profiler for duplicate queries.
  • Container parameters are compile-time, not runtime. If the bundle writes into $container->setParameter(), those values are frozen when the cache is warmed in prod. Editing a row won't change anything until cache:clear (or a dedicated warmup). Prefer reading values through a service instead of injected parameters when you need live updates.
  • Deploy ordering. If the bundle touches the DB during container compilation, cache:clear/cache:warmup will fail on a fresh deploy before migrations have run, or when the DB is temporarily unreachable. Check the bundle's boot logic and, if needed, warm the cache after doctrine:migrations:migrate.
  • Secrets do not belong here. The table is plain text and readable by anyone with DB access or a misconfigured admin screen. Encrypt sensitive values or keep them in environment variables.
  • Column length. The value column is often VARCHAR(255). Truncation errors on long JSON payloads are a frequent surprise — verify the mapping and migrate to TEXT if you store larger blobs.
  • Uniqueness and races. Ensure a unique index on name. Two concurrent set() calls on a new key can otherwise create duplicates. Wrap read-modify-write in a transaction or use an upsert.
  • Cache invalidation on write. The classic bug: value updates in the admin but the page keeps showing the old one. Always invalidate the settings cache key inside the same operation that persists the row.
  • Failure handling. Wrap reads in try/catch if the bundle queries eagerly during boot; a down database should degrade to defaults rather than a white screen. Log the failure once, not per getter call.
  • Testing. In unit tests, mock your Settings wrapper rather than the bundle's manager. For integration tests, point the bundle at an in-memory SQLite database and load a fixture schema so tests stay fast and isolated.
  • Debugging. Use debug:container to confirm the real service alias (they vary between versions), and doctrine:query:sql to verify what's actually stored — value formatting bugs (e.g., "0", "false", empty string) are common when everything round-trips as a string.
  • Extension points. You can usually override the entity class and manager service through the bundle's configuration; if not, decorate the manager service in your own services.yaml to add casting, validation, or auditing. Prefer decoration over forking — it survives upgrades.
  • Project age. With ~30 stars and a Symfony 2/3-era lineage, expect sparse docs and unmaintained compatibility with modern Symfony. Verify it installs cleanly against your framework version before committing; if it doesn't, the same pattern is easy to reimplement with a single entity, a manager service, and a cached loader — often a better long-term call than pinning an old bundle.
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.
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
cgv/localized-resource