networkrailbusinesssystems/activity-log
A Laravel package for recording and reviewing activity logs across your application. It provides a simple way to track user and system actions, store audit trails, and surface recent changes, helping teams monitor what happened, when, and by whom.
Treat this as a GOV.UK-flavoured audit-trail package for Laravel: install it, attach its logging trait/behaviour to the Eloquent models you care about, then render the recorded activity in an admin or record-detail page.
Minimal path:
composer require networkrailbusinesssystems/activity-log
Then inspect the package before wiring it in:
README.md — installation, published assets, route/UI conventions.composer.json — Laravel/PHP constraints and whether it depends on spatie/laravel-activitylog, GOV.UK Frontend, etc.config/activity-log.php — table name, log names, route prefix, middleware, retention.database/migrations — confirm the activity table and indexes.src/ — service provider, model, trait, controllers, Blade components.resources/views / routes — what UI and endpoints are provided versus what you must build.Publish and migrate what the README instructs, for example:
php artisan vendor:publish --provider="NetworkRailBusinessSystems\ActivityLog\ActivityLogServiceProvider"
php artisan migrate
First practical use case: add an “Activity” panel to a record page so caseworkers/admins can see who changed what and when. Attach the package trait to the model:
use NetworkRailBusinessSystems\ActivityLog\Traits\LogsActivity;
class CaseFile extends Model
{
use LogsActivity;
}
If the package follows Spatie conventions, configure what is logged:
public function getActivitylogOptions(): LogOptions
{
return LogOptions::defaults()
->logOnly(['status', 'owner_id', 'due_at'])
->logOnlyDirty()
->dontSubmitEmptyLogs()
->useLogName('case-file');
}
Then render activities for that record using the package’s provided view/component/controller if available, or query its activity model directly and paginate.
Use model traits for standard CRUD audit. Attach the package trait to models where an audit trail matters: applications, cases, licences, users, organisations. Prefer an allowlist of fields over logging everything. This keeps the activity feed readable and reduces the risk of storing sensitive values.
Log domain actions explicitly. For workflows that are not simple Eloquent updates, write an explicit activity entry from a service/action class after the transaction succeeds:
activity('case-file')
->performedOn($caseFile)
->causedBy(auth()->user())
->withProperties([
'from' => $oldStatus,
'to' => $newStatus,
'reason' => $reason,
])
->log('status changed');
If the package exposes its own helper/model, use that instead so the UI, log names, and retention rules stay consistent.
Build two views early. Day-to-day, teams usually need:
Use GOV.UK table/summary-list patterns, clear timestamps, causer names, event labels, and expandable property details. Eager-load causer and subject to avoid N+1 queries.
Integrate at the service layer, not only controllers. Log after successful state changes. For multi-step operations, consider a batch identifier if the package supports it, so related entries can be grouped in the UI. Avoid logging inside loops unless each entry is genuinely meaningful.
Wire causer and subject deliberately. Use causedBy(auth()->user()) for web requests. For console commands, imports, or queued jobs, set an explicit causer or a system label. If your GOV.UK service uses a custom guard or One Login integration, verify the morph relation and guard config.
Configure log names and retention per domain. Use names such as case-file, user-management, export, rather than one undifferentiated log. Set pruning/retention according to your service’s records policy. If the package provides routes, protect them with middleware and policies; an activity log can expose user behaviour and record history.
spatie/laravel-activitylog, confirm which version and whether you already have that table.logAll() on models containing PII. Activity properties are stored as JSON and may be exported or viewed by admins. Use field allowlists and redact secrets, tokens, passwords, and unnecessary personal data.subject_type/subject_id, causer_type/causer_id, log_name, and created_at. Paginate, filter, and prune. Do not load full history on every page view.logOnly includes the changed field, the update is dirty, auth is available, the correct database connection is used, and the log name/config is not filtering it out.How can I help you explore Laravel packages today?