imamsudarajat04/laravel-change-logs

A comprehensive change logs tracking package for Laravel 11+ that automatically tracks all model changes (create, update, delete, restore) with detailed audit trails

Installs: 4

Dependents: 0

Suggesters: 0

Security: 0

Stars: 2

Watchers: 0

Forks: 0

pkg:composer/imamsudarajat04/laravel-change-logs

v1.1.0 2025-12-07 05:07 UTC

This package is auto-updated.

Last update: 2025-12-07 05:07:47 UTC


README

Latest Version on Packagist Total Downloads

A comprehensive change logs tracking package for Laravel 11+ that automatically tracks all model changes (create, update, delete, restore) with detailed audit trails.

Features

โœจ Automatic Tracking - Zero configuration needed, just add a trait ๐Ÿ“ Detailed Logging - Track field-level changes with old/new values ๐Ÿ” Flexible Querying - Built-in scopes and filters ๐Ÿ‘ค User Context - Automatically captures user, IP, and user agent ๐Ÿท๏ธ Tagging Support - Categorize logs with custom tags โšก Queue Support - Async logging for better performance ๐Ÿงน Auto Cleanup - Scheduled cleanup of old logs ๐ŸŽฏ Polymorphic - Works with any Eloquent model ๐Ÿ”’ Security - Excludes sensitive fields (passwords, tokens) ๐Ÿ“Š Statistics - Built-in analytics and reporting

Requirements

  • PHP 8.2+
  • Laravel 11.0+
  • MySQL / PostgreSQL / SQLite

Installation

1. Install via Composer

composer require imamsudarajat04/laravel-change-logs

2. Install Package

php artisan vendor:publish --provider="Imamsudarajat04\\ChangeLogs\\ChangeLogsServiceProvider"

This will publish:

  • Configuration file: config/change-logs.php
  • Migration file: database/migrations/xxx_create_change_logs_table.php

3. Run Migrations

php artisan migrate

Basic Usage

Add Trait to Model

use Imamsudarajat04\ChangeLogs\Traits\HasChangeLogs;

class User extends Authenticatable
{
    use HasChangeLogs;
}

That's it! Now all changes to User model will be automatically tracked.

Access Change Logs

// Get all change logs for a model
$user = User::find(1);
$logs = $user->changeLogs; // Returns collection of ChangeLog

// Get recent logs
$recentLogs = $user->recentChangeLogs(5);

// Get logs by action
$updateLogs = $user->changeLogsByAction('UPDATE');

// Get logs for specific field
$emailChanges = $user->fieldChangeLogs('email');

// Check if model has logs
if ($user->hasChangeLogs()) {
    // ...
}

// Get last change
$lastChange = $user->lastChangeLog();

Query Change Logs Directly

use Imamsudarajat04\ChangeLogs\Models\ChangeLog;

// Using scopes
$logs = ChangeLog::action('UPDATE')->get();
$logs = ChangeLog::forModel(User::class)->byUser(1)->get();
$logs = ChangeLog::dateRange('2024-01-01', '2024-12-31')->get();
$logs = ChangeLog::withTag('important')->get();

// Chain multiple scopes
$logs = ChangeLog::action('UPDATE')
    ->byUser(1)
    ->dateRange('2024-01-01', '2024-12-31')
    ->limit(10)
    ->get();

Using Service/Facade

use Imamsudarajat04\ChangeLogs\Facades\ChangeLog;

// Query with filters
$logs = ChangeLog::query([
    'action' => 'UPDATE',
    'user_id' => 1,
    'start_date' => '2024-01-01',
    'end_date' => '2024-12-31',
])->paginate(20);

// Get statistics
$stats = ChangeLog::getStatistics();
// Returns: ['total' => 100, 'by_action' => [...], 'by_user' => [...], 'recent' => [...]]

// Cleanup old logs
ChangeLog::cleanup(365); // Delete logs older than 365 days

Advanced Usage

Customize Excluded Fields

class User extends Authenticatable
{
    use HasChangeLogs;

    public function getChangeLogExcludedFields(): array
    {
        return ['password', 'remember_token', 'api_token'];
    }
}

Custom Descriptions

class User extends Authenticatable
{
    use HasChangeLogs;

    public function getChangeLogDescription(string $action): ?string
    {
        return match($action) {
            'CREATE' => "User {$this->name} was registered",
            'UPDATE' => "User {$this->name} updated their profile",
            'DELETE' => "User {$this->name} was deleted",
            default => null,
        };
    }
}

Custom Tags

class Order extends Model
{
    use HasChangeLogs;

    public function getChangeLogTags(string $action): array
    {
        return match($action) {
            'CREATE' => ['order', 'new', 'customer-action'],
            'UPDATE' => ['order', 'modified'],
            default => ['order'],
        };
    }
}

Conditional Logging

class User extends Authenticatable
{
    use HasChangeLogs;

    public function shouldLogChanges(string $action): bool
    {
        // Don't log test users
        if (str_contains($this->email, '@test.com')) {
            return false;
        }

        return parent::shouldLogChanges($action);
    }
}

Temporarily Disable Logging

// For single model
User::withoutChangeLogs(function() {
    User::where('active', 0)->update(['status' => 'inactive']);
});

// For specific operations
config(['change-logs.enabled' => false]);
// Your operations here
config(['change-logs.enabled' => true]);

Artisan Commands

Install Package

php artisan change-logs:install

# Options:
--migrations    # Only publish migrations
--config       # Only publish config
--force        # Overwrite existing files

View Statistics

php artisan change-logs:stats

# With filters:
php artisan change-logs:stats --user=1
php artisan change-logs:stats --action=UPDATE
php artisan change-logs:stats --model="App\Models\User"
php artisan change-logs:stats --days=7

Cleanup Old Logs

php artisan change-logs:cleanup

# Options:
--days=90     # Custom retention days
--force       # Skip confirmation

Prune with Filters

php artisan change-logs:prune

# Options:
--model="App\Models\User"  # Prune specific model
--action=DELETE            # Prune specific action
--pretend                  # Dry run

Configuration

Publish and edit config/change-logs.php:

return [
    // Enable/disable globally
    'enabled' => env('CHANGE_LOGS_ENABLED', true),

    // Logging strategy
    'log_per_field' => false, // true = separate log per field, false = bulk

    // Track additional context
    'track_ip' => true,
    'track_user_agent' => true,

    // Exclude fields
    'hidden_fields' => ['password', 'remember_token'],
    'exclude_timestamps' => true,

    // Queue configuration
    'queue' => [
        'enabled' => false,
        'connection' => null,
        'queue' => 'default',
    ],

    // Auto cleanup
    'cleanup' => [
        'enabled' => false,
        'days' => 365,
    ],
];

Task Scheduling

Add to app/Console/Kernel.php:

protected function schedule(Schedule $schedule)
{
    // Cleanup logs monthly
    $schedule->command('change-logs:cleanup --force')->monthly();
    
    // Or use prune
    $schedule->command('change-logs:prune')->monthly();
}

Testing

composer test

Changelog

Please see CHANGELOG for more information on what has changed recently.

Contributing

Please see CONTRIBUTING for details.

Security

If you discover any security-related issues, please email imamsudarajat708@gmail.com instead of using the issue tracker.

Credits

License

The MIT License (MIT). Please see License File for more information.