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

Technical Evaluation

Architecture fit — the package does not fit, but the problem domain does. Despite being catalogued here as a Laravel/PHP package, makinacorpus/preferences-bundle is a Symfony bundle: it ships a Bundle subclass, a DI extension, and (almost certainly) Doctrine ORM mappings. Laravel has no bundle or compiler-pass lifecycle to hook into, and its container is a runtime resolver rather than a compiled one. Laravel does already ship a set of Symfony components (HttpFoundation, Console, Routing, Process, Mime, Translation, ErrorHandler, VarDumper, Finder), so a parallel-container bootstrap is theoretically possible — it is not something a TPM should approve for a preference store.

The caveat that makes this worth an evaluation slot at all: the capability is real and recurring. "Configuration that users edit at runtime, and which therefore cannot live in env vars or container parameters" is a genuine structural gap in most PHP applications. The opportunity: 7.51 score reflects the problem space. A TPM should treat this artifact as a reference design and a decision instrument, not a candidate dependency.

Integration feasibility — low, and three paths exist.

Path Effort TPM verdict
Install as-is via a Symfony-in-Laravel shim 3–6 weeks + permanent ops debt Reject
Fork, extract the domain core, rebuild wiring as a Laravel ServiceProvider 2–4 weeks incl. tests Only if the scoping model is genuinely novel to us
Build natively (Eloquent + cache + typed casts) or adopt spatie/laravel-settings 3–7 days Recommended

Technical risk — high, on four axes.

  1. License (GPL-2.0). Copyleft. Usually survivable for internal tooling or SaaS where no binaries are distributed, but a fork shared between business units counts as distribution, and it is incompatible with redistributing a proprietary Laravel product. Legal sign-off is a hard gate, not a parallel track.
  2. Abandonment. 1 star, 0 dependents, single-agency provenance. No community to absorb a fork, no security advisory feed we would be subscribed to, no supported-version matrix. Assume we own it on day one.
  3. Dependency conflict. Laravel 10/11/12 pin Symfony 6/7 components. A bundle of this vintage likely declares symfony/framework-bundle ^4/^5 and doctrine/orm ^2 — installing it either fails resolution or forces a downgrade of shared Symfony components, which is a whole-application risk rather than a local one.
  4. Undocumented storage contract. Typing/serialization, multi-tenant scoping, and cache invalidation are the parts that hurt in production and are exactly the parts the description omits.

Key questions to resolve before any code is written

  • Does it require symfony/framework-bundle, or only doctrine/orm plus a manager class? This moves feasibility from "weeks" to "days."
  • Do the declared require/require-dev constraints resolve against our composer.lock?
  • Is persistence Doctrine entities, raw DBAL, or an interface we can implement ourselves?
  • How are values typed and serialized, and is there a schema-versioning story when a preference definition changes?
  • Does it scope per-user, per-tenant, per-entity — or only a global namespace? What is the resolution order?
  • How is the read cache invalidated on write, and is it request-scoped or persistent?
  • What is upstream commit cadence over 24 months, and who is the actual maintainer?
  • Has legal cleared GPL-2.0 for our specific deployment model (SaaS vs. distributed/on-prem)?

Integration Approach

Stack fit — state the mismatch plainly to stakeholders. This is a near-zero-adoption Symfony bundle being evaluated for a Laravel codebase. The defensible TPM position is: we are evaluating the pattern, not the artifact. If we proceed, we proceed against a fork we control, never against upstream as a Composer dependency.

Recommended move before any fork. Audit spatie/laravel-settings (MIT, maintained, typed settings classes, migrations, per-model scoping) or a ~200-line internal settings table behind a cached repository interface. Either delivers ~90% of the value in a week. The only justification for forking is if this bundle exposes a specific data model — hierarchical scoping, a preference-definition registry — that we would otherwise design ourselves and consider differentiating. That is the question the spike must answer.

Migration path — greenfield only. Zero dependents means no installed base and nothing to migrate from. The migration is inward: if we fork, carry the schema into a Laravel migration, move the domain classes into app/ or a packages/ path repository, and pin by commit SHA (upstream will not produce release tags we can rely on).

Compatibility gates, in order:

  1. composer why-not makinacorpus/preferences-bundle against the current lock — this alone may end the evaluation in twenty minutes.
  2. Confirm PHP 8.2/8.3 support and no deprecated dynamic-property or Serializable patterns.
  3. Confirm no hard dependency on symfony/framework-bundle; if present, the fork must strip it.
  4. Decide Doctrine-vs-Eloquent before writing any adapter. Do not run two ORMs against one database on a small team.

Sequencing (if approved):

  1. Day 1–2: Composer feasibility spike plus a source read. Deliverable: a one-page "what actually ports" memo.
  2. Day 3–5: Legal review of GPL-2.0 against the deployment model. Hard gate.
  3. Week 2: Extract the domain core into a fork, delete bundle/DI scaffolding, add a PreferencesServiceProvider with bindings, publishable config, and a facade.
  4. Week 2–3: Implement the persistence contract (Eloquent) and a cache decorator against Illuminate\Contracts\Cache\Repository.
  5. Week 3: Test harness — round-trip typing, concurrent writes, invalidation on update/delete, tenant isolation, default fallback.
  6. Week 4: Integrate behind an internal PreferenceStore interface so the fork is swappable for a maintained package. This interface is the single most important deliverable — it caps the downside of the entire bet at one adapter swap.
  7. Week 4+: Only then expose to product surfaces (admin UI, API).

Operational Impact

Maintenance — we become the maintainer. With one star and no dependents there is no upstream to consume patches from and no realistic path to upstreaming a Laravel adapter. Budget 10–15% of one engineer's time in perpetuity for security review, PHP/Laravel major bumps, and bug response. Mitigate by keeping the fork thin: domain core only, Laravel wiring in our own namespace, a documented diff against upstream. If our own code grows past a few hundred lines, we have written the package and should drop the pretense and own it outright.

Support — none, by any channel. No vendor SLA, no reachable maintainer for a bundle of this footprint, no advisory feed. A support relationship with Makina Corpus would be a commercial consulting engagement and should be priced into the decision, not assumed. spatie/laravel-settings has paid support and a responsive maintainer — that asymmetry belongs in the comparison slide.

Scaling — the read path is the entire story. Preference resolution happens on every request for every user, which makes it one of the hottest queries in the system. Three concerns: (a) cache is mandatory, not an optimization — a per-request DB lookup per preference key is an N+1 hazard and will not survive load; (b) invalidation on write must be correct across processes, which rules out request-scoped memoization alone; (c) cache stampede — a deploy or flush triggers a synchronized miss across the fleet for the most popular keys, so plan for lock-based rebuild or jittered TTLs. Also model the growth curve: preference rows are user-generated and unbounded, so the unique index on (scope, scope_id, key) and the resolver query plan are first-class design artifacts. Multi-tenant scoping multiplies cache key cardinality — confirm the key includes the tenant dimension or you risk cross-tenant leakage, a security incident rather than a bug.

Failure modes to instrument for explicitly

  • Cache/DB divergence after a partial write or a missed invalidation — silent, and it presents as "my setting keeps reverting."
  • Missing default → null propagation into typed consumers, surfacing far from the cause.
  • Untyped coercion bugs ("false" is truthy) when values round-trip through JSON or strings.
  • Key-namespace drift: without a definition registry, keys become an unowned, undocumented vocabulary that no one can safely delete.
  • Write authorization absent — if the model permits any authenticated user to set any scope, you have a privilege-escalation surface; check whether the bundle enforces scope ownership.
  • No audit trail: "who changed this threshold, and when" becomes unanswerable, which is a compliance problem for operator-tunable values.
  • Secrets creeping into the preference table because it is the convenient place to put a value. Preferences are user-editable by definition; secrets belong in a secrets manager, full stop.

Ramp-up — deceptively shallow. A competent Laravel engineer can reproduce a typed scoped key/value store with cache in a week; there is no exotic technology here. The difficulty is not the code, it is the governance taxonomy the code encodes: separating deploy-time config, global admin settings, user preferences, feature flags, and secrets, and defining the resolution order (user → tenant → global default) before surfaces proliferate. Expect one to two days of design alignment with product and security before the first line is written. The bundle is most useful as input to that alignment conversation — a concrete, readable prior art that forces the team to answer "what is a preference, what is a flag, and what is a secret?" That is the real return on this evaluation, and it is available without taking the dependency.

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