klaude/eloquent-preferences
Add flexible key-value preferences to any Eloquent model with klaude/eloquent-preferences. Store per-model settings polymorphically, read and write them through a simple API, and keep configuration data organized without extra tables or boilerplate.
Architecture fit. klaude/eloquent-preferences is a conventional Laravel leaf dependency: a service provider, a publishable config and migration, and a HasPreferences-style trait that exposes a polymorphic preferences relation on any Eloquent model. It does not impose architectural opinions beyond the trait, so it composes cleanly with existing domain models and does not constrain how we structure controllers, services, or APIs. The trade-off is that preference semantics (typing, defaults, validation, caching) live in application code, not in the package.
Integration feasibility. Low effort: composer require, publish config/migration, add the trait to target models, backfill. Realistic estimate is one to three days for a pilot model plus a half-day for migration and backfill, assuming no naming collisions with an existing preferences or settings table. Feasibility hinges on the supported framework matrix, which the release notes do not state reliably.
Technical risk. Moderate, concentrated in four areas:
Key questions.
composer.json (illuminate/*, PHP constraint)? Does it cover Laravel 10/11, or only 9?spatie/laravel-settings, a JSON column, or fixed columns for our specific access patterns?Stack fit. Best fit is a Laravel 8/9-era application on PHP 8.0/8.1 that needs per-model, user-editable preferences without schema churn per new preference. Poor fit if we are already on Laravel 10/11 (unverified), or if preferences are few, stable, and hot-path — fixed columns or a JSON column would be simpler and faster.
Migration path. Publish config and migration, run in a staging environment first, verify the polymorphic index and column types against our DB engine. If consolidating existing settings columns, run a dual-write window: write to both old columns and preferences, backfill historical rows, read from preferences behind a feature flag, then drop the old columns after a soak period. Ensure the rollback path restores reads from the original columns before any data is deleted.
Compatibility. Do not accept the release notes' compatibility claim at face value. Validate the composer.json constraints against our pinned framework and PHP versions in a throwaway branch before committing. If Laravel 10/11 is unsupported, do not work around it with --ignore-platform-reqs; either pin the framework, fork and patch the constraint with a documented maintenance obligation, or select an alternative.
Sequencing.
PreferenceRepository contract) so the underlying implementation is swappable — this is the single highest-value risk mitigation and costs little.Maintenance. Expect to own more of this than a typical dependency. Pin the version, watch the upstream repo for releases, and budget a recurring review. Because the wrapper interface exists, an abandonment scenario degrades to a bounded rewrite of one adapter rather than a cross-cutting refactor.
Support. No vendor SLA. Upstream responsiveness is community-driven and uneven; the v0.6.0 notes suggest PRs are merged in batches. Internal documentation should capture our pinned version, the rationale, and the exit plan so support does not depend on tribal knowledge.
Scaling. One row per preference per model instance. The primary scaling concern is not storage but query count: hydrating a collection of models and reading preferences per model is a classic N+1. Mitigate by eager-loading the relation and, if read volume justifies it, adding an application-level cache keyed by model type and ID with explicit invalidation on write. Table growth is linear and predictable; the polymorphic index on (model_type, model_id) should be verified against real query plans once volume is meaningful.
Failure modes.
Ramp-up. Low. A mid-level Laravel developer should be productive in under half a day; the API surface is small and idiomatic. The real ramp-up cost is not the package but the operational discipline around it: the version pin, the wrapper interface, and the upgrade runbook. Document those three artifacts alongside the integration so the next engineer inherits a decision, not a surprise.
How can I help you explore Laravel packages today?