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

Preferences Bundle Laravel Package

makinacorpus/preferences-bundle

Symfony bundle for managing user preferences: define configurable preference keys, persist per-user values, and read or write settings through a simple API. Integrates with Symfony apps to centralize user-specific configuration.

View on GitHub
Deep Wiki
Context7

Getting Started

First, confirm the framework. This is a Symfony bundle (makinacorpus/preferences-bundle), not a Laravel package. If you're on Laravel, the realistic starting point is reading the source as a design reference, not composer require. Run composer why-not makinacorpus/preferences-bundle first — it will usually resolve your whole evaluation in a minute because the bundle targets symfony/framework-bundle ^4/^5 and doctrine/orm ^2, while Laravel 10/11/12 pin Symfony 6/7 into the same lockfile.

Where to look first (if you're reading the source):

  • The *Bundle class and its DI Extension — tells you how the manager service is wired and what config keys are published.
  • The preference manager / service interface — the actual read/write API you'd call.
  • The Doctrine entity or repository — the persistence contract, and therefore the data model.
  • Resources/config/ (or config/) — where the preference keys and defaults are declared.

If you are in Symfony and it installs cleanly: register the bundle in config/bundles.php, run the Doctrine migration for its table, publish/override the bundle config, then inject the preference manager into a controller or service. First use case: a single global, admin-editable value (e.g. items_per_page) read via the manager with a code-defined default, so nothing breaks when the row is absent.

If you are in Laravel (the expected case): skip the install. Copy the model — scope / key / typed value / default with a resolution order (user → tenant → global) — and implement it in ~200 lines with Eloquent, a PreferenceStore interface, and a cached resolver. That's ~3–7 days and gets you 90% of the value with an MIT-clean, maintained footprint.

Implementation Patterns

Define preference keys centrally, not inline. Whether you use the bundle's config or your own, keep a registry of known keys with type and default. This is what prevents the "settings table becomes a bag of random strings" failure mode this package is trying to avoid.

Read through a resolver, write through an explicit setter. In Symfony, autowire the manager and call its typed getter with a fallback default. In a Laravel reimplementation, put the resolver behind an interface (PreferenceStore) so the caller never knows if the value came from the user row, the tenant row, or the global default.

// Laravel-shaped borrowing of the pattern, not the bundle's API
interface PreferenceStore {
    public function get(string $key, ?int $userId = null, mixed $default = null): mixed;
    public function set(string $key, mixed $value, ?int $userId = null): void;
    public function forget(string $key, ?int $userId = null): void;
}

Resolution order is the whole design. User scope → tenant scope → global default → hardcoded fallback. Encode it once in the resolver, test it explicitly, and never let callers pick a scope by hand in business logic.

Cache the read path, invalidate on write. Preferences are read on nearly every request; a cache decorator around the store is not optional. In Laravel, wrap the Eloquent implementation with Illuminate\Contracts\Cache\Repository, key by preferences:{scope}:{userId}:{key}, and flush the relevant keys on set()/forget().

Separate the four settings categories before you build anything:

  • Deploy-time config (env / container parameters) — not this package's job.
  • Global admin settings — this package's job.
  • Per-user preferences — this package's job, its actual scope.
  • Feature flags and secrets — not this package's job. Use Pennant (Laravel) or a flags service; use a secrets manager for secrets.

Conflating these is the single most common mistake in "settings" implementations, and the bundle's own docs are honest that its domain is only the middle two.

Integrate at the boundaries you already have. In Symfony, inject the manager into controllers/services. In Laravel, bind the PreferenceStore interface to your Eloquent implementation in a service provider, expose a thin facade for controllers, and keep the store out of Blade/JSON directly.

Prefer composition over forking the bundle. If you genuinely need a different backend (Redis, a remote settings service), implement the persistence interface rather than editing the bundle. If the interface doesn't exist, that itself is a signal the fork will cost more than a rewrite.

Gotchas and Tips

License gate, before code. GPL-2.0 is copyleft. Fine for internal SaaS where you don't distribute binaries, risky for anything shipped or embedded, and incompatible with Apache-2.0 code in the same linked work. Get this reviewed before anything lands in a repo — it is not a parallel track.

Composer resolution is the first real test. The bundle's require constraints almost certainly don't co-exist with Laravel's pinned Symfony 6/7 components. Force-installing it means downgrading shared Symfony packages — a whole-app risk, not a local one. If composer why-not fails, the evaluation is over for the install path; move to the pattern.

Assume you are the maintainer. 1 star, 0 dependents, single-org provenance. There is no security advisory channel, no upstream patch stream, and no realistic path to upstreaming your adapter. If you fork, pin by commit SHA (there are no reliable tags) and keep the diff small.

Do not run two ORMs. The bundle leans on Doctrine; Laravel uses Eloquent. Bridging them (or standing up a second Doctrine-managed connection) is a lasting operational tax. Pick one persistence layer before writing any adapter — usually Eloquent.

Preferences are user-editable by definition. Never store secrets, API keys, or tokens here. If a value would be embarrassing to display in an admin UI, it belongs in a secrets manager, not a preferences table.

Typed values and schema changes are undocumented. The description does not cover serialization, type coercion, or how preference keys evolve. Round-trip test every type you support (bool, int, string, JSON) and decide a migration story before product surfaces depend on it.

Cache invalidation on write is the silent failure. The read path is cheap to add and the write path is easy to forget. Add an explicit test: set() then get() through the cache returns the new value, and forget() restores the default.

Wrap the whole thing behind an internal interface. The single most valuable deliverable, whether you fork or rebuild, is PreferenceStore as a Laravel-idiomatic contract. That caps the downside of the decision at one adapter swap — to your own implementation, or to spatie/laravel-settings if the internal version stalls.

Extension points, in preference order: (1) a Laravel-native build behind an interface, (2) a thin fork with the DI/bundle scaffolding stripped and a ServiceProvider wired in its place, (3) the Symfony-in-Laravel shim — which you should not greenlight for a settings table.

The honest one-liner for the team: adopt the pattern, not the package. The pattern is a scoped, typed key/value store with a defined resolution order and a cached read path; the package is a Symfony-specific shell around it that you'd end up rewriting anyway.

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.
adachsoft/changelog-linter
adachsoft/collection
payerurl/telegrambot-crypto-payment-instant-payout
dskripchenko/laravel-hybrid-search
riorizkyrainey/lara-ced
mehedimi/static-vel
zharp/zharp
nonsapiens/bigquery-model-sync
lgu-bayambang-ict-office/lgu-laravel-development-standards
andydefer/laravel-support
se7enxweb/flysystem
lampwick/laravel
jeslage/statamic-emojis
micahdshackelford/rmap-laravel
draftsmaninc/draftsman
square-bit/laravel-volition
himito/laravel-mailman
htinlynn/genius-helper
maco-studios/hephaestus
adachsoft/php-code-style