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

Filament Model Settings Laravel Package

quadrubo/filament-model-settings

Filament plugin for managing per-model settings in your admin panel. It adds a settings page and reusable form component so you can store, edit, and read model-specific configuration values directly from Filament with a simple API.

View on GitHub
Deep Wiki
Context7

Getting Started

This assessment covers quadrubo/filament-model-settings at v2.0.1. That patch release is a follow-up to the v2.0.0 major; nothing in the v2.0.1 changelog signals breaking changes, so anything you build against v2.0.0 semantics carries forward. Treat v2.0.0 as the reference point for upgrade notes (Filament major alignment, PHP/Laravel floor) and v2.0.1 as a drop-in patch.

Day-to-day, the package solves one specific problem: giving individual Eloquent records their own editable settings, with a Filament UI to edit them — as opposed to app-wide config or a single settings singleton. If your need is "the tenant/team/user/project record has its own preferences that an admin edits in the panel," this is the right shape of tool. If your need is global app settings, use spatie/laravel-settings instead; don't bend this package to that job.

Minimal path to first value:

  1. composer require quadrubo/filament-model-settings and publish + run the migration (there is a settings storage table; check the published file for column names before you write queries against it).
  2. Create a settings class for the model — a plain PHP class with typed public properties and (typically) validation rules. This class is the contract; everything else is plumbing.
  3. Attach the package trait to the Eloquent model that owns the settings.
  4. Register the plugin on your panel provider, mapping model → settings class.
  5. Open the panel, navigate to the model's settings UI, save, and confirm a row lands in the settings table and $model->settings (or the package's accessor) returns your values.

Where to look first, in order: the published config (panel/UI options), the published migration (storage shape), then the README's model-registration example. Confirm the exact trait name, settings-class base/interface, and accessor signature against the README for the installed version before you write production code against them — v2 reorganised namespaces and these are the identifiers most likely to differ from older blog posts and Stack Overflow answers.

First use case to ship: a single NotificationSettings class on User with three booleans, wired into the panel, read in a queued job. That exercises save, load, defaults, and serialisation in one afternoon and surfaces every gotcha below before you commit to a wider rollout.

Implementation Patterns

Settings class as the single source of truth. Define typed properties with sane defaults and put validation rules next to them. Every read site ($user->settings->notify_email) then depends on one class, not on string keys scattered across the codebase. Resist adding a parallel config() fallback — you get two sources of truth and drift within a sprint.

Read-through accessor, write-through form. The Filament form is just a view over the settings class. Keep business rules in the class (validation, casting, defaults) so seeders, console commands, API endpoints, and the panel all behave identically. If a rule only exists in the Filament form schema, it doesn't exist for the importer.

Per-model resolution helper. Wrap lookups in a small service or repository method rather than calling the accessor inline everywhere:

final class SettingsResolver
{
    public function for(Model $model): ModelSettings
    {
        return $model->settings ?? ModelSettings::defaults();
    }
}

You will want one place to change when you add caching, tenancy scoping, or default-merging later.

Defaults for unsaved models. New records have no settings row. Decide explicitly whether reads return null, a defaults object, or lazily create a row, and encode that decision once. Lazy-creating on read inside a GET request is a trap — it writes during page render and breaks read-only replicas and tests that assert query counts.

Multi-tenant panels. Register the plugin per panel and scope the settings lookup by the tenant. Verify the settings table has (or you add) a tenant discriminator; sharing one settings row across tenants is a data-leak class of bug, not a cosmetic one.

Policy-gated editing. Gate the settings page/tab behind a policy ability (updateSettings) rather than relying on panel access alone. Settings pages are commonly attached to resources where "can view" and "can reconfigure" are different permissions — support staff who can read a customer record should not necessarily toggle that customer's notification routing.

Queues and long-running workers. Load settings at job dispatch time or re-read at the start of handle(), not in the constructor of a singleton service. A worker that boots once and caches a model's settings will serve stale values for the life of the process.

Migrations from a previous version. Because v2 is a major, expect namespace and registration changes rather than storage changes. Diff the published migration from your installed copy before deploying; if the table shape moved, write a data migration rather than trusting migrate to be non-destructive.

Gotchas and Tips

  • The v2.0.1 changelog is a bare compare link. There are no narrative notes, so you cannot infer behaviour from release text alone. Before bumping, read the diff between the two tags (or at minimum the CHANGELOG/commits touching namespaces, migrations, and the plugin class) and run your test suite against the new tag. Patch version ≠ guaranteed no-op when the notes are empty.
  • Two cache layers will bite you. Eloquent's own model instance caching plus any settings cache plus Octane's long-lived state means a saved setting may not appear until the next request, or may appear where it shouldn't. Decide on explicit invalidation on save; don't assume the package does it for you.
  • ->refresh() after save in tests. Assertions on $model->settings immediately after a Filament form submit often read a stale instance. Re-fetch from the database to test what actually persisted.
  • N+1 on index tables. Showing a "settings configured" badge on a resource table is the classic accidental N+1. Eager-load the settings relation (->with('settings')) or use withCount. Watch DB::listen on the first table you build.
  • JSON/text payload limits. If settings are stored as a serialised blob, a growing settings class eventually hits column limits or produces unreadable rows. Prefer flat, typed properties; avoid nesting arbitrary arrays in settings "for flexibility."
  • Casting is your job. Values round-trip through storage as strings/JSON. "false" is truthy, "0" is falsy, and null vs. absent-key are different. Cast on read in the settings class and unit-test the round-trip for booleans, enums, and dates — this is where most real bugs in settings packages live.
  • Testing surface. Use Filament's livewire()/callAction() test helpers for the settings page and RefreshDatabase with the package migration. A settings package you can't test in isolation becomes a package you stop trusting.
  • Defaults drift. When you add a property to the settings class, existing rows have no value for it. Centralise "missing key → default" resolution; otherwise old tenants silently break on a feature flag you added.
  • Concurrency. Two admins saving the same model's settings form is last-write-wins across the whole payload, not per-field. For settings where that matters (billing thresholds, routing rules), consider optimistic locking with updated_at and a clear "settings changed, please review" UX.
  • Extension points to prefer. Keep the settings class small and inject behaviour through the model trait and a resolver service. If you find yourself patching the package's Filament page, first check whether the published config or a custom page subclass covers the case — forked vendor pages are the most expensive thing to carry across a v3 major.
  • Upgrade discipline. Pin the version, read the tag diff on each patch while the changelog remains a link, and keep one integration test that saves and reloads a settings value. That single test catches nearly every regression this package can introduce.
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.
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
elmogy/larafast
xeviant/laravel-paystack
gorilladash/laravel-website-sdk
martialbe/flysystem-oss
chondal/3312client
jeroen-g/flickr
opscale-co/nova-genbi
itsjustvita/laravel-retention
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log