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

Laravel Polymorphic Settings Laravel Package

sitesource/laravel-polymorphic-settings

Laravel Polymorphic Settings lets you attach flexible key-value settings to any Eloquent model through a polymorphic relationship, with a simple API for storing, retrieving, updating, and managing configuration-like data per record.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit. The package models settings as a polymorphic key-value relation (model_type/model_id → key → value), which is the canonical Laravel shape for "per-entity configuration without schema churn." It slots into Eloquent via a trait/interface on the owning model, so it composes with existing domain models rather than introducing a parallel persistence layer. For teams already storing per-user or per-tenant preferences in JSON columns, this is a direct, normalized substitute. Encryption is opt-in per key, which is the right default posture: sensitive values (API tokens, webhook secrets) get encrypted, non-sensitive values stay queryable.

Integration feasibility. Low-to-moderate. There is no external service, no queue dependency, and no front-end contract. Integration is a migration, a trait, and optionally a cache configuration change. The existence of a first-party-adjacent Filament adapter (laravel-polymorphic-settings-filament v0.1.0) is a positive signal that the API surface is usable by admin tooling, but it also means the only observed production consumer is a sibling project from the same author — not independent validation.

Technical risk. The dominant risk is maturity, not design. The package is at v0.1.3, has 0 stars and 0 dependents, and its most recent release is a bug-fix release for two correctness defects in the cache layer:

  • A dotted-key read could cache a literal row under a key that a nested put() did not invalidate, serving stale data indefinitely (TTL-bounded).
  • forget() was a no-op for cache invalidation when the underlying row was already absent, leaving orphaned cache entries with no public cleanup path.

Both are now fixed (129 tests, 217 assertions), and the failure modes are the dangerous kind — silent staleness rather than exceptions. The fact that these were found by a downstream integration rather than by the package's own tests is the meaningful signal: the cache layer's invariants were underspecified at v0.1.2, and there is no guarantee a v0.1.4 does not reveal a third. The dotted-key contract is also subtle by design: put('a.b', x) stores literally, while get('a.b') falls back to root traversal, and v0.1.3's fix trades a cache hit for a DB round-trip on every literal dotted read. That is a correct trade, but it means "transparent caching" is not uniformly transparent.

Key questions for the maintainer / spike.

  1. What is the supported Laravel and PHP version matrix, and what is the pre-1.0 breaking-change policy?
  2. Is there a documented index on (model_type, model_id, key), and is the uniqueness constraint enforced at the DB level?
  3. How does encryption key rotation work — is re-encryption supported, and what happens on decrypt failure with a rotated/lost APP_KEY?
  4. What is the cache key namespace and invalidation contract under concurrent writers (two processes writing the same root key)?
  5. Are settings cascade-deleted when the owning model is deleted, or does the table accumulate orphans?
  6. Is multi-tenancy addressed (per-tenant cache isolation, tenant-scoped queries), or is that left entirely to the application?
  7. Is there a query/search API, or is this read-by-key only? (Implication: settings cannot be filtered in SQL without bypassing the package.)

Integration Approach

Stack fit. Best fit is a conventional Laravel monolith or modular monolith on Laravel 10/11+, using Eloquent, with Redis or a shared cache store. It is a poor fit if settings must be queried in aggregate (WHERE setting = x), joined into reports, or audited with per-change history — the package is a key-value accessor, not a settings domain model. It is also a poor fit where settings are owned by a service outside the Laravel app.

Migration path. Treat this as an additive, reversible change:

  1. Add the settings table via the package migration; add the composite index before any backfill.
  2. Attach the trait to one or two low-risk models first (user preferences, notification toggles), not to billing or auth configuration.
  3. Backfill from existing JSON columns with a one-shot artisan command or job; keep the old column readable during a dual-read window.
  4. Cut reads over to the package behind a config flag, then cut writes, then drop the legacy column in a later release.
  5. Enable encryption only after key management is settled — retrofitting encryption onto populated rows requires a re-write pass, so decide before the backfill, not after.

Compatibility. Pin exact versions (0.1.3), not ^0.1. Pre-1.0 semver permits breaking changes in patch releases, and the v0.1.2 → v0.1.3 change alters cache behavior for dotted keys. If the team cannot upgrade promptly, the documented escape hatch is POLYMORPHIC_SETTINGS_CACHE_ENABLED=false — acceptable for settings, which are typically low-QPS, but it must be a conscious, monitored setting rather than a silent fallback. Confirm the Filament adapter version is pinned against the same core version.

Sequencing. (a) One-week spike: table, trait on a scratch model, cache on/off comparison, concurrent-write test. (b) Write an ADR recording the decision and the pinning policy. (c) Pilot in a non-critical domain with cache enabled. (d) Observe for one release cycle. (e) Expand to additional models. Do not sequence encryption last; do not sequence cache-enable before the pilot, because the cache layer is the part with the observed defect history.

Operational Impact

Maintenance. Small code surface, MIT license, no external runtime. The real maintenance burden is governance: a 0-star, 0-dependent package with a single author is a bus-factor-1 dependency. Mitigate by vendoring the source into the repo or maintaining a private fork with the ability to patch — at this size that is cheap insurance, and it converts an availability risk into a routine merge.

Support. No commercial support, no SLA. Support is GitHub issues plus reading the changelog. Budget for the team owning the integration to be the de facto maintainer. The Filament adapter is effectively the reference consumer; watch its issue tracker as an early-warning system for core defects.

Scaling. One row per key per model. Read cost is one query per uncached key, and dotted-literal reads are deliberately uncached in v0.1.3 — so a screen rendering 30 settings should be collapsed into a single root read or eager load, not 30 key lookups. Write cost includes cache invalidation. The composite index on (model_type, model_id, key) is mandatory; without it, polymorphic lookups degrade as the table grows. Cache store choice matters: a per-node file cache will produce inconsistent reads across app servers, so use a shared store.

Failure modes.

  • Silent staleness — the historical defect class. Fixed for the reported paths, but any external writer (manual SQL, sibling service, another package) bypassing the model layer reintroduces it. Rule: all writes go through the package API.
  • Cache store eviction or flush — degrades to DB reads; correctness preserved, latency increases. Acceptable.
  • Lost or rotated encryption key — encrypted values become unrecoverable, with no in-package recovery. This is the highest-severity operational risk and belongs in the runbook, not the code review.
  • Orphaned rows — model deletion without cascade leaves settings behind; needs a periodic cleanup or a model deleting hook.
  • Concurrent root writes — last-writer-wins on nested arrays; acceptable for settings, unacceptable if this is repurposed for anything transactional.

Ramp-up. Low for a Laravel-fluent engineer: half a day to read the source and tests, one to two days to integrate the first model. The TPM cost is front-loaded — the ADR, the version-pinning policy, the encryption/key-rotation decision, and the "all writes through the API" rule. Those four artifacts are what convert a plausible v0.1 package into something the team can operate. Given the maturity signals (0 stars, 0 dependents, defects found only by a sibling integration), the recommendation is pilot, don't standardize: adopt behind a pin and a fork-ready posture, and revisit for broader use once there is evidence of independent production consumers or a 1.0 release.

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.
jinas/dhivatar
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