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 Immutable Attributes Laravel Package

taldres/laravel-immutable-attributes

A Laravel package for defining immutable Eloquent model attributes that can be set once but never changed afterward, helping protect critical values from accidental updates.

View on GitHub
Deep Wiki
Context7

Product Decisions This Supports

  • Deciding which fields are business invariants, not just columns. The package forces an explicit product conversation: which attributes must never change after creation (invoice numbers, external/provider IDs, tenant or account ownership, ledger entry amounts, contract effective dates, issued-at timestamps, signed-document hashes, idempotency keys). That list is a product artifact worth having regardless of whether you adopt the package.
  • Build vs. buy for guardrails. The capability is small and easy to replicate in-house (a saving/updating model hook plus a trait). Buying here means accepting a third-party dependency to avoid ~a day of internal work and to inherit a declarative convention (#[Immutable]) that is self-documenting in code review. Given MIT licensing and a tiny API surface, the lock-in cost is low and the fork cost is near zero.
  • Roadmap input for auditability and compliance work. If your roadmap includes SOC 2, financial reporting integrity, or "who changed this record" requirements, this is a cheap first layer — but only a first layer. It prevents application-level mutation; it does not produce an audit trail, and it does not stop raw SQL, query-builder bulk updates, or database-console changes. Use it to scope the real investment (DB constraints, triggers, or an auditing/event-sourcing package) rather than as a substitute.
  • Prioritizing incident classes. This targets a specific, recurring failure mode: a well-meaning developer or admin panel writes over a field that downstream systems depend on. If postmortems show "record mutated unexpectedly," this is a low-cost, high-signal mitigation.
  • Use cases that fit cleanly: invoice and receipt numbering, payment/transaction references, immutable line-item amounts, externally assigned IDs (Stripe, ERP, tax authority), ownership/tenant assignment, published-content slugs once live, and any field copied into an external system of record.
  • Use cases that do not fit: anything needing a version history or "correct with an audit trail" workflow. Immutability that throws is a hard stop; regulated corrections usually need a reversing entry or an amendment record, not an exception.

When to Consider This Package

Consider it when:

  • The app is Eloquent-centric and the invariants live at the model layer, not spread across raw SQL, jobs, and imports.
  • You have a short, stable list of truly immutable fields — not a broad "we'd prefer nobody edits this" policy.
  • You want the rule expressed next to the model (one attribute per field) so it survives refactors and is visible in code review.
  • You can accept a very early-stage dependency: 0 stars, 0 dependents, a single maintainer, and a low overall quality signal. Treat it as "vendored code you happen to install," pin the version, read the source, and be prepared to fork.
  • You have tests that will catch the exception path (the failure mode is a thrown exception during save — that needs to be handled, logged, and surfaced to users, not swallowed).

Look elsewhere — or build it in-house — when:

  • You need a hard guarantee. Application-layer checks are bypassable via DB::table()->update(), raw queries, seeders, and console access. If the requirement is regulatory or financial, pair with database constraints, triggers, or an append-only design. This package alone will not satisfy an auditor.
  • You need history, not prevention. Use an auditing package (e.g., activity logging) or event sourcing so corrections are recorded rather than rejected.
  • The immutable set is large or volatile. Annotating dozens of fields, or fields that legitimately change during migrations/backfills, creates friction and workaround pressure (saveQuietly, disabling events) that erodes the guarantee.
  • You rely on bulk operations. Confirm with engineering exactly which write paths are intercepted — mass update(), upsert, insert, saveQuietly, soft-delete/restore, and queued jobs. If your architecture leans on bulk writes, the guard will be inconsistent and therefore misleading.
  • Dependency governance is strict (regulated, security-reviewed, or long-support-horizon environments). An unmaintained single-maintainer package behind a compliance claim is a liability.

Questions to route to engineering before committing: Which Eloquent events are hooked? Are updates blocked at saving or updating? What happens on saveQuietly, model refresh, replication, and seeders? Does it throw a typed, catchable exception? Is the field list validated at boot or discovered per-save? Coverage of the test suite?

How to Pitch It (Stakeholders)

To executives — one paragraph: This is a small, MIT-licensed guardrail that lets us declare in code which record fields can never change after creation — invoice numbers, payment references, ownership, published identifiers. It converts a class of "someone changed the wrong field and broke a downstream system" incidents into a loud, immediate error at save time, and it costs roughly nothing to adopt: one attribute per field, no new infrastructure, no vendor, no data migration. It is a guardrail, not a compliance control — it operates at the application layer only, so it complements rather than replaces database constraints and audit logging. Given the project is early-stage (no meaningful adoption yet), I recommend a time-boxed pilot on one or two high-value models, with the code read and the version pinned, and the assumption that we may fork it. Expected effort: under a week, including the internal policy work of agreeing on the immutable field list — which is the durable output regardless of the tool we choose.

To engineering — the ask: Evaluate on one model with genuinely immutable fields, verify which write paths are actually intercepted (bulk updates and saveQuietly are the open questions), and confirm the exception is typed and handled. If coverage is thin, the pattern is ~50 lines of our own code and we keep the #[Immutable] convention.

Recommendation: Adopt the convention now; adopt the package only after a short spike confirms write-path coverage. Opportunity is real; the artifact is not yet proven.

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