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

Configuration Bundle Laravel Package

spipu/configuration-bundle

Symfony bundle for database-backed application configuration. Define typed settings, store values in the database, and access them through a service for editable, centralized app config with validation and caching support.

View on GitHub
Deep Wiki
Context7

Getting Started

Install the bundle and its Doctrine dependency, then register it:

composer require spipu/configuration-bundle
// config/bundles.php
return [
    // ...
    Spipu\ConfigurationBundle\SpipuConfigurationBundle::class => ['all' => true],
];

Create the configuration table. The bundle ships its own Configuration entity, so point Doctrine at it and run a diff/migrate:

# config/packages/doctrine.yaml
doctrine:
    orm:
        mappings:
            SpipuConfigurationBundle:
                is_bundle: true
php bin/console doctrine:schema:update --dump-sql   # inspect first
php bin/console doctrine:migrations:diff
php bin/console doctrine:migrations:migrate

Define your keys. This is the file you'll live in — it is the source of truth for which keys exist, the DB is the source of truth for their values:

# config/packages/spipu_configuration.yaml
spipu_configuration:
    config:
        app:
            name:
                type: string
                default: 'My App'
            contact_email:
                type: string
                default: '[email protected]'
            maintenance_mode:
                type: boolean
                default: false

Seed the new definitions into the database (run this after every deploy that touches the YAML):

php bin/console spipu:configuration:init

First use case — the classic one this bundle exists for: a settings page someone in marketing can edit without a deploy. Read values anywhere via the injected manager:

use Spipu\ConfigurationBundle\Service\ConfigurationManagerInterface;

final class HomeController
{
    public function __construct(private ConfigurationManagerInterface $configuration) {}

    public function __invoke(): Response
    {
        return $this->render('home.html.twig', [
            'name' => $this->configuration->get('app.name'),
            'maintenance' => $this->configuration->get('app.maintenance_mode'),
        ]);
    }
}

And in Twig, a global function is registered:

<h1>{{ get_configuration('app.name') }}</h1>

Look first at: the bundle's README, the config/packages/spipu_configuration.yaml tree you build yourself, and the ConfigurationManager service (spipu.configuration.manager). Everything flows through those three.

Implementation Patterns

Definitions vs. values. Treat the YAML as schema and the DB row as data. type and default live in YAML; only value is written at runtime. This means code review of settings changes happens in git, while runtime edits happen in an admin UI or command — clean separation.

Admin editing surface. The bundle ships form types (ConfigurationType, plus per-type field types). Build a small admin controller that loads getAll() grouped by your config tree and binds to the form. This is usually the whole point of adopting the bundle: you get typed fields and validation for free rather than hand-rolling a settings CRUD.

Programmatic writes. For feature flags toggled by an admin action or an importer:

$this->configuration->set('app.maintenance_mode', true);
// flush depends on how you inject it — check whether the manager
// flushes internally or defers to the unit of work around it
$this->em->flush();

Reading efficiently. Don't call get() inside a loop over 500 rows — each call may hit the DB. Instead load once and cache at the service layer:

public function __construct(private ConfigurationManagerInterface $configuration) {}

private ?array $cache = null;

private function all(): array
{
    return $this->cache ??= $this->configuration->getAll();
}

Better still, wrap this in your own Settings facade that exposes typed getters (isMaintenance(), contactEmail()) so domain code never sees string keys. This also lets you swap the backing store later and is the single most valuable pattern for keeping the bundle from leaking through the codebase.

Typed values. Values round-trip through the DB as strings and are cast back per type. For structured settings use the JSON type and cast to array on read; for enums, validate in the form type rather than in YAML.

Integration with API/serializer. If the bundle exposes an API layer (it does via spipu/api-bundle in related Spipu packages), guard writes behind ROLE_ADMIN. Config-write endpoints are a privilege-escalation footgun if left open.

Environment overrides. For anything secret (API keys, DB credentials) do not put it here — use Symfony secrets/.env. Use this bundle only for non-sensitive, human-editable business settings.

Gotchas and Tips

The YAML and DB drift silently. Add a key, forget spipu:configuration:init, and get() returns the default from YAML at runtime while the DB has no row. That's fine until someone edits it in the admin UI — the form may not show it, or the write may fail on a missing row. Wire spipu:configuration:init into your deploy script.

init must be idempotent-safe in your pipeline. It should add new keys without overwriting edited values, but verify that behavior against your version — run it against a staging copy first, and never run anything described as "sync" against production without a backup if you're unsure.

Flushing semantics. set() may or may not call flush() internally depending on version and how the manager is wired. If a write silently doesn't persist, check whether you need $em->flush() after set(). Conversely, if it does flush internally, batching many set() calls becomes slow — wrap in a transaction.

Booleans and empty strings. get('app.flag') returns a typed bool only if the definition says type: boolean; otherwise '0' is a truthy string. A missing/blank value is not the same as false — always set explicit defaults.

Caching. If you add a cache layer, remember the bundle itself does not invalidate it on set(). Add an explicit invalidation in your Settings facade after writes, or you'll chase a ghost bug for an afternoon where the admin UI shows the new value and the front end shows the old one.

Entity override. You can usually extend/replace the shipped Configuration entity via config and doctrine mapping overrides if you need extra columns (an updatedBy, audit trail, per-tenant scoping). Check the bundle config tree for the entity class parameter before you fork anything.

Extension points to reach for: custom configuration types (register a type so the form and caster know how to handle, e.g., a date range or a currency), form-type overrides for field rendering, and the Twig extension if you want additional helper functions.

Low-maturity reality check. One star and zero dependents means the integration surface (Doctrine version, Symfony version, PHP version) is narrower than the docs imply. Pin versions in composer.json, read the actual composer.json constraints of the release you install, and expect to patch a deprecation or two across a major Symfony upgrade. Budget a day to vendor-fork if you're on the bleeding edge.

Debugging. Because values live in a table, the fastest debugging tool is SELECT code, value, type FROM configuration WHERE code LIKE 'app.%' — verify the row exists, is typed correctly, and has a non-null value before blaming the code. A second common trap is reading the wrong key namespace (app.name vs app_name); grep the YAML definition rather than trusting memory.

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.
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource
noith/settings