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

Audit Livewire Laravel Package

liberusoftware/audit-livewire

Audit Livewire brings Laravel audit trails to Livewire apps, automatically recording model changes, user actions, and component activity. Review who changed what and when with clear, searchable logs that simplify debugging, accountability, and compliance.

View on GitHub
Deep Wiki
Context7

Getting Started

Know what this package is before you install it. liberusoftware/audit-livewire is a presentation adapter — the Livewire layer of the Liberu audit module suite. It renders audit records; it almost certainly does not create them. The recording engine lives in the companion audit domain module (typically liberusoftware/module-audit, usually wrapping owen-it/laravel-auditing). If you're expecting this package to instrument your models, you'll be disappointed; if you already have auditing writing to an audits table and want a UI for it, that's the sweet spot.

Minimal path in:

composer require liberusoftware/audit-livewire

Because it's part of a modular suite, check composer.json in the repo first for its require block — that tells you which core module version and which Livewire major it expects. Get those pinned before you write a single component, otherwise you'll spend an afternoon on Livewire 3 vs 2 API drift ($this->dispatch() vs $emit(), for example).

Where to look first, in order:

  1. src/Livewire/ (or src/Http/Livewire/) — the actual components. This is the package; everything else is views and wiring.
  2. resources/views/livewire/ — how the trail is marked up, and therefore what you can override.
  3. config/ — table name, model bindings, pagination size, date format. Confirm it exists and is mergeable via php artisan vendor:publish.
  4. tests/ — if present, they're the only reliable documentation you're going to get at 0 stars.
  5. routes/ — whether it ships a full-page route or is embed-only.

Your first use case should be the narrowest one: a "History" tab on an existing resource detail page. Add the Auditable trait to a model, make two or three edits, then drop the component in:

<livewire:audit.trail :auditable="$invoice" />

Adjust the tag to whatever the component alias actually is (grep for Livewire::component( in the service provider). Verify three things immediately: the trail loads, it paginates, and it respects the actor (who made the change). If the actor column is blank, your morph map or user relation config is off — see Gotchas.

Do not start by wiring this into a global admin activity feed. Per-record trails are the low-risk entry point and they flush out config problems fast.

Implementation Patterns

Per-record trail on a show page. The canonical use. Mount the component with the model as a parameter, let it resolve its own query. Keep the parent page's own data loading separate — don't pass the audit collection in as a prop unless the component explicitly supports it, or you'll lose live pagination.

Filter and search via the query string. Presentation adapters in this suite generally expose filter properties ($event, $actorId, $from, $to) as Livewire properties. Bind them with #[Url] so a filtered view is shareable and survives a refresh:

#[Url(as: 'event')]
public string $eventFilter = '';

Watch for collisions if two audit components sit on the same page — namespace the URL keys.

Diff rendering is the real integration work. A raw old_values / new_values JSON dump is unreadable. The pattern that pays off:

  • Map each changed key through a formatter registry (status → badge, amount → money, assigned_to → user name).
  • Render only keys present in new_values, diffed against old_values; treat null → value and value → null explicitly so creates and deletes read correctly.
  • Mask sensitive fields (password, remember_token, tokens) at the view level even if the core module already redacts — defense in depth.

Detail drawer instead of navigation. Emit an event from the row ($this->dispatch('audit-selected', id: $audit->id)) and let a sibling modal component load the full payload. Keeps the list query light and avoids a route per audit entry.

Authorization belongs in the component, not the Blade. Gate the mount and every subsequent action:

public function mount(AuditableContract $auditable): void
{
    Gate::authorize('viewAudit', $auditable);
    $this->auditable = $auditable;
}

Also gate the export path if you add one — it's the usual hole.

Extend rather than fork. Override the published Blade views for markup changes (resources/views/vendor/audit-livewire/...). Subclass the component only when you need new query behaviour, and keep the parent's method signatures intact so a package update doesn't silently break you.

Testing. Livewire::test(AuditTrail::class, ['auditable' => $post])->assertSee('updated') gets you a regression net cheaply. Build a handful of fixtures covering created/updated/deleted and a multi-field update — those three cases catch most rendering regressions.

Composition. In a modular Liberu install, treat this as a leaf: it depends on the audit core, never the reverse. If you need audit display inside another module, depend on this package's component, not on the core's models directly.

Gotchas and Tips

It's presentation-only — debugging the wrong layer is the #1 time sink. If nothing appears, check in this order: is the model Auditable? Is a row in the audits table (php artisan tinker → Audit::count())? Does the component's query scope match (tenant, morph type)? Only then suspect the package. Roughly nine times in ten the audit was never recorded.

Zero stars, zero dependents, NOASSERTION license. Treat this as internal-first tooling. NOASSERTION means the SPDX scanner couldn't identify the license — get it reviewed before you ship it in anything you redistribute. Vendor it or pin the exact commit; there's no ecosystem pressure keeping the API stable.

Version coupling across the module suite. The package's composer.json constraints against the audit core are the contract. If you bump the core module and this package lags, you get cryptic "class not found" or property-not-found errors from compiled Livewire components. Run php artisan view:clear and php artisan livewire:discover (or the Livewire 3 equivalent) after any suite update — stale compiled component classes cause failures that look like logic bugs.

N+1 on the actor relation. Each audit row typically resolves ->user. Eager load it in the component's query (->with('user') or whatever the configured actor relation is) or a 50-row page becomes 51 queries. Same for any auditable eager load on a global feed — that one is polymorphic and worse.

Polymorphic type mismatch. If you use a morph map (Relation::enforceMorphMap), audit rows store the alias, not the FQCN. If the package queries by auditable_type = Post::class, your trail comes back empty. Check the stored value and align the map — and be aware old rows written before the morph map will keep the FQCN.

Pagination and query-string conflicts. Two paginated Livewire components on one page share ?page=. Use #[Url(as: 'audit_page')] and set a distinct $pageName on each. Otherwise page 2 of the audit trail scrolls your main table.

Large JSON payloads. A bulk update on a wide model produces a multi-kilobyte diff. Truncate long values in the view (Str::limit) and consider not rendering old_values in list mode at all. Memory blows up in hydrate, not in the query, so it won't show in your SQL log.

Hiding the UI is not authorization. The component is addressable from the client; a @can around the Blade include protects nothing. Gate inside mount() and inside any action that loads or exports data.

Custom table names. If your audit core uses a non-default table, the package's hardcoded model or query may not follow the config. Verify against config('audit.drivers.database.table') and, if it's hardcoded, that's your first fork or PR candidate.

Release dates in the future. The listed release date (2026-10-26) is nonsense metadata. Don't infer maturity from it — read the git log instead.

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.
abbasudo/artisan-route
mirvan/ippanel
ignibyte/aic-framework
glavweb/data-schema-bundle
glavweb/datagrid-bundle
tacticmedia/scim-server
uni-method/frame
neika-ai/sdk
adachsoft/php-code-style
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
adachsoft/api-version-bundle
cgv/localized-resource
noith/settings
kda/laravel-package