amarenkov/laravel-mutable-content
A Laravel package for adding mutable content to Eloquent models. Attach editable content records to any model and manage them through a simple API, making it easier to build CMS-style features without custom content tables. Lightweight and easy to integrate into existing Laravel apps.
This is an audit/change-log package: it records model changes as Entry rows and exposes two read-path helpers that turn raw attribute diffs into human-readable strings — Entry::describe() (per-entry) and LogHelper::describeChanges() (batch, e.g. all entries for a record or request).
composer require the package, then publish and run its migrations (php artisan vendor:publish --tag=...; check the package's README/composer.json extra.laravel block for the exact tag) and php artisan migrate. The entries table is the single source of truth — everything else is derived.Entry::describe() and LogHelper::describeChanges(). They are the contract you'll build UI and notifications on top of, so skim them before wiring up logging.Entry::latest()->first()->describe() in tinker. That confirms the field-type formatting path (including money) is what you expect before you build a history tab around it.created_at, map through describe(), and render as a timeline. Keep the raw changes JSON alongside the description if you need a "show raw diff" toggle.LogHelper::describeChanges() when one logical operation touches multiple entries (a bulk import, a multi-model transaction). It returns the aggregated, formatted description set — use it directly in flash messages, Slack/webhook payloads, or email digests rather than re-implementing string building.money fields render as 10.50 $ (decimals + currency from the field definition) — see the v0.7.8 note below. Treat other types (dates, booleans, enums) the same way: define the field correctly and let the package format it, instead of hand-formatting in Blade.describe(). That way formatter fixes (like this release) apply retroactively to old entries without a migration.describe() output in feature tests where the wording is part of your UX. For the data, assert the changes array/isDirty payload instead — that's the stable part.money values in LogHelper::describeChanges() and Entry::describe() now show as formatted amounts with the field's decimals (10.50 $) instead of the raw JSON value ("10.5"). If you snapshot-test description strings, inline-asserted text, or have cached/exported descriptions (CSV, PDFs, sent emails stored in DB), they will change. Update assertions and consider re-rendering cached output.changes JSON is untouched — this only affects the read path. Don't write migrations to "fix" existing entries.money field declared with different precision than the underlying data will produce surprising rounding in descriptions; keep the field definition and DB column precision aligned.$entry->changes (raw) next to $entry->describe() and compare. A wrong type declaration on the field is the usual cause of JSON leaking into the description.str_replace-ing output from describe(), which will break on the next formatting change like this one.How can I help you explore Laravel packages today?