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 Model Settings Laravel Package

dragon-code/laravel-model-settings

Store per-model key-value settings in Laravel with dragon-code/laravel-model-settings. Attach typed settings to any Eloquent model, read and write them through a simple API, and keep configuration data with your records without extra tables.

View on GitHub
Deep Wiki
Context7

Getting Started

This release (1.3.0) is a good entry point: the package now ships a full Docusaurus documentation site and generator commands for localization files, so the first stop should be the docs rather than the source.

Minimal setup:

  1. Require the package and publish its config/migrations:
    composer require <vendor>/<package>
    php artisan vendor:publish --tag=<package>-config
    php artisan migrate
    
  2. Read the docs sections on package boundaries and the focused API (added in #99) before touching models — they define what the package owns versus what your app owns.
  3. Add the settings trait/contract to the model that should own settings (typically User, Team, or a dedicated Setting model).
  4. Create your first settings class/model with defaults, then read/write through the owner:
    $user->settings->theme = 'dark';
    $user->settings->save();
    

First use case: per-owner application preferences (theme, locale, notification toggles). Define defaults on the settings model rather than manufacturing a "default owner" row — see the ID 0 note below.

Use the new localization generator commands (#73) early if your settings have human-readable labels or validation messages you intend to translate.

Implementation Patterns

Owner-scoped settings. Treat settings as always belonging to an owner (morph relation or model key). Owner validation is hardened in 1.3.0 (#95), so passing an arbitrary/stale owner ID will fail loudly rather than silently attach settings to the wrong record. Resolve owners through Eloquent relationships where possible.

Defaults are not rows. 1.3.0 distinguishes persistent defaults from a model with ID 0 (#100). Model defaults on the settings class and read through the accessor; do not create or query a sentinel id = 0 record to represent "unset". This makes fresh owners and migrated data behave consistently.

Payload casts per model and per key. #97 allows cast definitions scoped to a specific settings model and a specific setting key. Use this for structured values (arrays, DTOs, enums) instead of manually json_encode/json_decode-ing in accessors. Keep casts next to the settings definition so bulk reads and writes deserialize the same way as single reads.

Blank JSON is stored explicitly. #101 means an intentionally blank JSON payload persists as blank rather than collapsing to null/absent. If your UI distinguishes "never configured" from "configured as empty", this is now reliable — check for key existence/null, not truthiness.

Bulk mutations with bounds. #96 adds bounded-query bulk mutations and an overridable purge. For large owner sets, use the bulk API with an explicit bound/chunk size rather than iterating and saving one model at a time:

Settings::query()
    ->forOwners($ownerIds)
    ->updatePayload(['notifications' => true]);

Override the purge behavior in your settings model when deletion semantics differ from the package default (e.g. soft-deleting settings or cascading cleanup).

Typed exceptions instead of logs. #102 replaces package logging with typed bulk mutation exceptions. Wrap bulk operations in try/catch against the specific exception types and surface partial-failure information to the caller/job. This fits naturally with queued jobs: let the exception fail the job rather than discovering problems in logs later.

Localization workflow. Use the generator commands (#73) to scaffold translation files, then translate them (the docs site itself is localized, #80/#75). Keep generated files in version control and regenerate on upgrade.

Gotchas and Tips

  • Upgrading from earlier versions: the logging removal (#102), default/ID-0 distinction (#100), and explicit blank JSON handling (#101) are behavior changes even though they are listed under "Changed". Audit any code that greps logs for bulk mutation failures, relies on a 0-ID default record, or treats blank JSON as null.
  • Catch the right exception. Bulk mutation failures now throw typed exceptions; a generic catch (\Throwable) will swallow the useful detail. Catch the specific types and log/report them yourself.
  • Bounds are not optional in spirit. Bounded bulk mutations protect you from unbounded queries, but an incorrectly chosen bound can split work awkwardly. Choose sizes consistent with your queue/transaction strategy and make the purge override idempotent.
  • Owner validation failures usually mean you passed an ID from a stale request, a deleted model, or the wrong morph type. Validate ownership at the boundary (form request/policy) rather than catching the package exception deep in a service.
  • Casts must be registered where both reads and writes see them. A cast defined only for a single key will not apply to bulk payload updates that bypass that key's definition — verify with a round-trip test.
  • Generated localization files are overwritten. Review diffs after running the generator; keep custom translations in files the generator does not own, or re-apply them.
  • Docs are now the primary reference. The Docusaurus site (plus metadata/crawler setup, #83) documents API boundaries explicitly; check it before extending internals. Extension points to prefer: purge override, per-model casts, and settings model customization — not modifying vendor code.
  • Test the "unset vs blank" path. Add a regression test asserting a fresh owner returns defaults while an explicitly blank JSON setting returns blank, so future upgrades cannot silently merge the two states.
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.
robertmarney/lara-hierarchial-collections
simonschaufi/rule-doc-generator
emissaoja/emissaoja
blackbricksoftware/gravityforms-civicrm-form-processor
al-rahabi/fancy-crud
jinas/dhivatar-component
mltstephane/laravel-quality
bernskiold/laravel-talentlms
bernskioldmedia/laravel-form-architect
youbar/easy-crud
c-point-labs/laravel-hostyourai
dbravoan/dbcms-admin-theme-dbcms
dbravoan/dbcms-theme-db-cyber
dbravoan/dbcms-blocks-basic
dbravoan/dbcms-module-content-audit
dbravoan/dbcms-module-ai-assistant
paygate-to/paygate-php
padosoft/askmydocs-connector-base
defstudio/supercharged-carbon
bernskioldmedia/laravel-matomo