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 Filament Activity Log Laravel Package

bestora/laravel-filament-activity-log

A Filament plugin for browsing and managing activity logs—track model changes, user actions, and events in a dedicated panel resource with filtering, timelines, and easy integration into your Laravel admin.

View on GitHub
Deep Wiki
Context7

Getting Started

  • Install the package with Composer and make sure spatie/laravel-activitylog is installed and migrated first — this package renders activity records, it does not create them:
    composer require bestora/laravel-filament-activity-log
    php artisan vendor:publish --tag="filament-activity-log-config"
    php artisan vendor:publish --tag="filament-activity-log-translations"
    
  • Register the plugin on the panel(s) you want the activity browser in:
    ->plugin(\Bestora\FilamentActivityLog\FilamentActivityLogPlugin::make())
    
  • Look first at config/filament-activity-log.php. The resources array is the control surface: which ActivityResource class is used, which columns are shown, and (as of v0.0.3) resources.hide_properties_column_by_default, which controls whether the "Changes" column is hidden in the table.
  • Make a model auditable and confirm data flows end to end:
    use Spatie\Activitylog\Traits\LogsActivity;
    use Spatie\Activitylog\LogOptions;
    
    class Post extends Model
    {
        use LogsActivity;
    
        public function getActivitylogOptions(): LogOptions
        {
            return LogOptions::defaults()->logFillable()->logOnlyDirty();
        }
    }
    
  • First use case: edit a Post in the panel, then open the activity resource, click into the record, and you'll see the causer, event, timestamp, and (v0.0.3) a linked subject plus a "Changes" section showing old → new values.

Implementation Patterns

Linking subjects to resources. v0.0.3 turns the subject column in the table and the subject field on the view page into links to the related record's edit page. The link is resolved via the activity's subject model's resource; if no resource (or no record) can be resolved, no link is rendered. This is opt-in by consequence: if your model has a Filament resource, you get links for free.

Mapping child models onto a parent resource. For models that don't have their own resource (pivot-ish models, child records, polymorphic sub-types), implement HasCustomActivityResource on the model and return the resource you want the subject to link to:

use Bestora\FilamentActivityLog\Contracts\HasCustomActivityResource;

class PostComment extends Model implements HasCustomActivityResource
{
    public static function getActivityResource(): string
    {
        return \App\Filament\Resources\PostResource::class;
    }
}

This is the supported extension point for keeping navigation coherent when one resource owns several auditable models.

Reading the diff. The view page renders a dedicated "Changes" section built by reusing the properties view. The section is hidden entirely when the activity has no diff (e.g. created events where old is empty, or activities logged without logOnlyDirty). Design your LogOptions accordingly — logOnlyDirty() plus dontSubmitEmptyLogs() gives you the cleanest diffs to display.

Column visibility policy. Because the "Changes" column is now visible by default, decide per panel whether that's desirable. Busy activity tables get wide fast; if you only care about the diff on the detail page:

// config/filament-activity-log.php
'resources' => [
    'hide_properties_column_by_default' => true,
],

Users can still toggle the column via the table's column manager, so this is a default, not a lock.

Localisation. The changes key now ships in all bundled locales, so non-English panels no longer show a raw translation key for the new section. If you maintain custom translations, re-publish (or diff) the translations to pick up the new key; a missing changes key falls back to the raw key string rather than breaking the page.

Testing the link resolution. v0.0.3 adds tests asserting getResourceUrl() returns no link when the activity has no resolvable subject. Mirror that in your own feature tests: assert getResourceUrl() is null for orphaned activities (deleted subject, model without resource), and non-null for the happy path. It's the cheapest regression guard for custom HasCustomActivityResource implementations.

Gotchas and Tips

  • Upgrade behaviour change: the "Changes" column flipping to visible by default is the one thing that will visibly alter existing panels. Nothing breaks, but tables get wider. Publish/refresh the config and set hide_properties_column_by_default to true if you want v0.0.2 behaviour.
  • Config cache: after changing the config, run php artisan config:clear (or config:cache in deploy). A stale cached config is the usual cause of "I set the option but nothing changed".
  • Silent no-link fallbacks: subject links render only when a target resolves. If links are missing, check in this order — (1) does the subject model have a resource, (2) is HasCustomActivityResource returning a resource class that actually exists, (3) does the record still exist, (4) is the current user authorized to view/edit that resource. Authorization failures look identical to "no resource configured".
  • Soft deletes and morph maps: deleted subjects and morph-map aliases that no longer resolve produce no link. That's intentional, but it means historical activity rows can be partly unlinked — don't build UI assumptions on links always being present.
  • Trait vs. resource mismatch: HasCustomActivityResource returning a resource for a different model than the subject is fine for navigation but confusing for users who land on a parent edit page. Prefer it only for genuinely child records (e.g. PostComment → PostResource).
  • Missing diffs: a "Changes" section that never appears is usually a logging-configuration problem, not a rendering one. Check that the model logs attribute changes (logFillable()/logOnly()), uses logOnlyDirty(), and that the activity isn't a created/deleted event with empty old.
  • Extension points to reach for before forking: the resources config array (swap in your own resource class), the HasCustomActivityResource contract (link mapping), and published translations (wording). Customising columns on the resource subclass is cheaper than overriding the whole table.
  • Growth: activity tables grow monotonically. Add pruning on the activity_log table side (activitylog:clean) and keep the table's default sort on created_at descending — the diff section makes the detail page much heavier to read, and reviewers will thank you for not making them paginate 200 rows to find today's change.
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.
mehedimi/laravel-amp-mail
happones/laravel-vue-i18n-generator
jwerd/inertia-table
siberfx/flysystem-wasabi
hollyit/token-replace
ippanelcom/laravel-sdk
adachsoft/changelog-linter
adachsoft/collection
payerurl/telegrambot-crypto-payment-instant-payout
dskripchenko/laravel-hybrid-search
riorizkyrainey/lara-ced
mehedimi/static-vel
zharp/zharp
nonsapiens/bigquery-model-sync
lgu-bayambang-ict-office/lgu-laravel-development-standards
andydefer/laravel-support
se7enxweb/flysystem
lampwick/laravel
jeslage/statamic-emojis
micahdshackelford/rmap-laravel