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

Settings Bundle Laravel Package

lst/settings-bundle

Laravel settings bundle for centralizing application configuration. Store and retrieve settings through a simple API, keep values organized, and manage options without scattering config across your codebase. A lightweight foundation for consistent runtime settings.

View on GitHub
Deep Wiki
Context7

Getting Started

First, the reality check that shapes everything else. lst/settings-bundle is a Symfony bundle (Bundle class, DI extension, Doctrine ORM entities/repositories). It has no ServiceProvider, no facade, no publishable config/settings.php. In a Laravel app you cannot composer require it into a working state — the value you extract day-to-day is the pattern, not the package. Treat it as a reference implementation to read once and reimplement (~1–2 days).

Read the source in this order (small surface area):

  1. *Bundle.php — what services get registered.
  2. DependencyInjection/*Extension.php — config tree and defaults.
  3. Entity/Setting.php — the schema (key, value, type).
  4. Repository/SettingRepository.php / manager service — read/write and type-coercion semantics. This is the part worth copying.

First use case: an admin-editable runtime setting (a feature flag or a threshold) that ops can change without a deploy.

Minimal Laravel reimplementation:

// migration: settings table
$table->string('key')->unique();
$table->text('value')->nullable();
$table->string('type')->default('string'); // string|int|bool|float|array|json
$table->string('group')->default('default');
$table->timestamps();
// app/Services/SettingsManager.php — public API mirroring the bundle
public function get(string $key, mixed $default = null): mixed;
public function getBool(string $key, bool $default = false): bool;
public function set(string $key, mixed $value, string $type = 'string'): void;
public function forget(string $key): void;

Bind it in a SettingsServiceProvider, resolve lazily, and seed defaults so no code path depends on a missing row.

Implementation Patterns

Typed getters with fallback defaults — the single feature that justifies the bundle's existence. Copy the semantics: getInt, getBool, getFloat, getJson/getArray, each accepting a default so callers never do ?? + cast gymnastics.

Manager behind an interface, injected — never a global helper. The bundle's DI wiring is the point (in Symfony). In Laravel, bind SettingsManager (an interface) in the container and inject it. That keeps the swap window small if you ever replace it.

$this->app->singleton(SettingsManager::class, fn ($app) =>
    new CachedSettings(new DatabaseSettings($app['db']), $app['cache'])
);

Cache decorator with write-through invalidation — non-negotiable. Settings are read on nearly every request; a naive DB read per request is a latency and load problem. Wrap the DB manager in a cached decorator that forgets the key on write.

class CachedSettings implements SettingsManager {
    public function get(string $key, mixed $default = null): mixed {
        return Cache::rememberForever("settings.$key",
            fn () => $this->inner->get($key, $default));
    }
    public function set(string $key, mixed $value, $type = 'string'): void {
        $this->inner->set($key, $value, $type);
        Cache::forget("settings.$key");
    }
}

Group / namespace column — the bundle is a single flat global table. Add a group column (or prefix keys) now if you ever expect per-tenant, per-environment, or per-feature scoping. Retrofitting scope into a flat global table is painful.

Seed defaults via migration/seeder — so behavior is defined by data, not by code falling back to null. This also makes the admin panel self-documenting.

Admin surface via Artisan or Filament/Nova resource — settings without a UI become a DBA-only artifact and rot. Add an audit column (updated_by) and a timestamp while you're there.

Reading the same table from a Symfony service (interop only). If a sibling Symfony app owns the table and Laravel reads it, mirror the exact column names and type strings the bundle uses, and read the source to confirm how it serializes arrays/JSON. Do not let bundle types leak into your domain code.

Test the coercion edges — nulls, empty strings, "0", "false", JSON arrays, and mixed-case booleans. This is the highest-risk silent-bug area.

Gotchas and Tips

  • There is no Laravel install path. The bundle only bootstraps inside a Symfony kernel. composer require will not give you a working settings API here — plan to port or reimplement from day one.
  • Never resolve settings during register(). If you eagerly load settings when the container boots, an unreachable DB makes the whole app unbootable. Resolve lazily on first access; fail soft to defaults where safe.
  • Type coercion is where production bugs live. Decide and test what "false", "0", "", and null mean for each type. The bundle's semantics are the contract to copy — don't invent your own mid-project.
  • No caching means a DB round trip per request. The bundle gives you none out of the box. Add it before production, cache to a shared store (Redis), and invalidate on write. Per-node file caches will diverge and produce "works on one worker" bugs.
  • Guard against per-request writes. The settings table is meant to be admin-driven and bounded (hundreds of rows). Any code path writing settings per request/user turns it into an unbounded event log.
  • Cache stampede after invalidation or deploy: add TTL jitter and a lock on repopulation.
  • Plaintext secrets. The bundle has no encryption. Forbid storing credentials/API keys here until you add encryption at rest — otherwise anyone with DB read or a backup has them.
  • Schema drift. Use migrations, not doctrine:schema:update-style tooling. If you mirror the entity, confirm JSON/boolean column types behave across MySQL/Postgres/SQLite.
  • You own this package. 0 stars, 0 dependents → no security review, no downstream bug discovery, no support. If you copy code, pin the source commit and vendor/fork it rather than depending on the repo. Check the license for fork rights.
  • Version constraints before any Symfony-side use: PHP version, Symfony 5/6/7, and Doctrine ORM 2 vs 3 (the 2→3 jump is a breaking migration).
  • Extension points to lean on if you ever sit in Symfony: decorate the repository/manager service and wrap it behind your own interface immediately — that's the difference between a two-week swap and a two-month one if the bundle dies.
  • Key collisions. Flat global keyspace with no namespace: use a group column or a feature./integration. prefix convention from the start.
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.
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
adachsoft/api-version-bundle
elsayed85/laravel-api-exceptions
ouhssini/laravel-demo-mode
daworks/ncloud-outbound-mailer-driver
gp247/cms
ignibyte/aic-gates
nexa-merchant/blog
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
shitoudev/permissionmanager