hanifhefaz/user-model-activity
Installation
composer require hanifhefaz/user-model-activity
php artisan vendor:publish --provider="Hanifhefaz\UserModelActivity\UserModelActivityServiceProvider"
config/usermodelactivity.php) and migration for the user_model_activities table.Run Migration
php artisan migrate
user_model_activities table to store activity logs.Enable Activity Tracking
Add the HasActivity trait to your Eloquent model:
use Hanifhefaz\UserModelActivity\Traits\HasActivity;
class User extends Model
{
use HasActivity;
}
First Use Case
created (with created_at, user_id, and payload).updated (with updated_at, user_id, changeset diff, and old/new values).deleted (with deleted_at, user_id, and payload).Example:
$user = new User(['name' => 'John Doe']);
$user->save(); // Logs creation
$user->name = 'Jane Doe';
$user->save(); // Logs update
Model-Level Tracking
HasActivity trait to any Eloquent model to enable automatic logging.activityFields() method:
class Post extends Model
{
use HasActivity;
public function activityFields()
{
return ['title', 'content', 'published_at'];
}
}
User Association
user_id of the authenticated user performing the action.config/usermodelactivity.php:
'user_resolver' => function () {
return auth()->user() ?? null;
},
Querying Logs
UserModelActivity model to fetch logs:
$logs = UserModelActivity::whereModelType('App\Models\User')
->whereModelId(1)
->orderBy('created_at', 'desc')
->get();
Event-Based Extensions
activity.created, activity.updated, or activity.deleted events:
event(new CreatingUserModelActivity($user, $activity));
Bulk Operations
Activity::logBulk() (if supported):
User::where('active', false)->update(['active' => true]);
// Logs each update individually (if configured).
Middleware for Admin Context
Attach middleware to admin routes to ensure logs include the correct user_id:
Route::middleware(['auth', 'admin'])->group(function () {
// Admin-only routes
});
Soft Deletes
Enable soft deletes on the UserModelActivity table to preserve logs even if models are restored:
class UserModelActivity extends Model
{
use SoftDeletes;
}
Storage Customization Override the default storage (e.g., database) by binding a custom logger in the service provider:
$this->app->singleton('usermodelactivity.logger', function () {
return new CustomLogger();
});
API Logging
Combine with Laravel’s log facade to cross-reference API activity:
Log::info('User updated', ['user_id' => auth()->id(), 'changes' => $changes]);
Performance Overhead
'queue_logging' => env('QUEUE_LOGGING', false),
Missing User Context
user_id (e.g., CLI commands or automated tasks) may lack accountability.UserModelActivity::setUser($user);
Diff Algorithm Limitations
activityFields() to specify simple fields or extend the diff logic.Migration Conflicts
user_model_activities tables.--force cautiously.Event Ordering
activity.* events may execute in unexpected orders.event(new CustomEvent($activity))->afterCommitting() for consistency.Log Location
Check the storage/logs/laravel.log for errors during logging (e.g., missing columns).
user_model_activities table matches the migration schema.Activity Payload Inspect the raw payload with:
dd(UserModelActivity::latest()->first()->payload);
Disabled Logging Verify the trait is applied and logging isn’t disabled in config:
'enabled' => env('USER_MODEL_ACTIVITY_ENABLED', true),
Custom Loggers Extend the logger to support additional storage (e.g., Elasticsearch):
class ElasticsearchLogger implements LoggerInterface
{
public function log($model, $event, $payload)
{
// Custom logic
}
}
Activity Filters
Add scopes to the UserModelActivity model for common queries:
class UserModelActivity extends Model
{
public function scopeByModel($query, $model)
{
return $query->where('model_type', get_class($model));
}
}
Webhook Notifications Trigger webhooks on critical activities:
UserModelActivity::created(function ($activity) {
if ($activity->event === 'deleted') {
Http::post(config('services.slack.webhook'), [
'text' => "Model {$activity->model_type} deleted by {$activity->user_id}"
]);
}
});
Activity Retention Implement a cron job to purge old logs:
// app/Console/Commands/CleanupLogs.php
public function handle()
{
UserModelActivity::where('created_at', '<', now()->subMonths(6))->delete();
}
How can I help you explore Laravel packages today?