PHP code example of soullessthread / laravel-audit-log

1. Go to this page and download the library: Download soullessthread/laravel-audit-log library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

soullessthread / laravel-audit-log example snippets


use soullessthread\AuditLog\Concerns\HasAuditLog;

class Invoice extends Model
{
    use HasAuditLog;

    // Columns to watch ('*' = all non-excluded columns)
    protected array $auditColumns = ['status', 'total', 'paid_at'];

    // Events to capture (all three are the default)
    protected array $auditEvents = ['created', 'updated', 'deleted'];

    // Optional: write to a dedicated table instead of the shared audit_logs
    protected ?string $auditTable = 'invoice_audit_logs';

    // Columns stored as '[REDACTED]' — merged with config sensitive_columns
    protected array $auditSensitive = ['card_last4'];

    // Columns to skip even when $auditColumns is ['*']
    protected array $auditExclude = ['internal_note'];

    // Optional: store the full row snapshot on every UPDATE (see below)
    protected bool $auditLogAll = true;
}

// Laravel 11+ (bootstrap/app.php)
->withMiddleware(function (Middleware $middleware) {
    $middleware->appendToGroup('web', \soullessthread\AuditLog\Middleware\SetAuditContext::class);
    $middleware->appendToGroup('api', \soullessthread\AuditLog\Middleware\SetAuditContext::class);
})

// Laravel 10 (app/Http/Kernel.php)
protected $middlewareGroups = [
    'web' => [
        // ... Authenticate::class must come before this
        \soullessthread\AuditLog\Middleware\SetAuditContext::class,
    ],
];

class User extends Model
{
    use HasAuditLog;

    protected array $auditColumns  = ['name', 'email'];
    protected array $auditRelations = ['roles', 'permissions'];

    public function roles(): BelongsToMany
    {
        return $this->belongsToMany(Role::class);
    }

    public function permissions(): BelongsToMany
    {
        return $this->belongsToMany(Permission::class);
    }
}

protected array $auditRelations = [
    'roles',                            // minimal: just FKs, insert + delete only

    'permissions' => [
        // Extra pivot columns to , 'deleted', 'updated'],

        // Redact sensitive pivot columns (merged with config sensitive_columns)
        'sensitive'   => ['granted_by'],

        // Optional: write pivot logs to a custom table
        'audit_table' => 'permission_pivot_logs',
    ],
];

// All role assignments for a user
AuditLog::query()
    ->where('table_name', 'role_user')
    ->where('row_id', $user->id)
    ->latest('created_at')
    ->get();

// Only detachments
AuditLog::query()
    ->where('table_name', 'role_user')
    ->where('event_type', 'deleted')
    ->get();

use soullessthread\AuditLog\Facades\AuditLog;

// All changes to a specific model instance
AuditLog::for($invoice)->latest('created_at')->get();

// Filter by event type
AuditLog::for($invoice)->ofEvent('updated')->get();

// Everything that happened in the same request / command / job
AuditLog::session($sessionUuid)->get();

// All changes made by a specific user
AuditLog::byUser(auth()->user())->get();

// All changes that came from a specific route
AuditLog::fromSource('route:invoices.update')->get();

// Combine scopes freely (returns an Eloquent Builder)
AuditLog::for($invoice)
    ->ofEvent('updated')
    ->where('user_id', $userId)
    ->latest('created_at')
    ->paginate(20);

$entry = AuditLog::for($invoice)->ofEvent('updated')->latest('created_at')->first();

$diff = $entry->getDiff();
// ['status' => ['old' => 'pending', 'new' => 'paid'], 'total' => ['old' => 100, 'new' => 150]]

$entry->hasColumnChanged('status'); // true

$entry = AuditLog::for($invoice)->ofEvent('updated')->latest('created_at')->first();

AuditLog::restoreTo($invoice, $entry); // re-applies $entry->old_values via $invoice->update()

$schedule->command('audit:prune')->daily();

// config/audit-log.php
'context_extras' => fn (\Illuminate\Http\Request $request) => [
    'tenant_id' => tenant()->id,
],

AuditLog::tag(['tenant_id' => $tenantId]);
// This re-pushes context to the DB connection immediately

public function handle(): void
{
    AuditLog::context()->setUser((string) $this->userId, 'App\Models\User');
    app(\soullessthread\AuditLog\Trigger\TriggerManager::class)
        ->pushContext(AuditLog::context()->toArray());

    // ... rest of job
}

class Order extends Model
{
    use HasAuditLog;

    protected array $auditColumns = ['status', 'total', 'paid_at', 'notes'];

    // Store ALL audited columns in old_values/new_values on every UPDATE.
    protected bool $auditLogAll = true;
}

AuditLog::for($model)
    ->ofEvent('updated')
    ->whereJsonContains('changed_columns', 'deleted_at')
    ->get();

'auth_guards' => ['web', 'api'],

// Laravel 11+ (bootstrap/app.php)
->withMiddleware(function (Middleware $middleware) {
    // API routes only check the 'api' guard
    $middleware->appendToGroup('api',
        \soullessthread\AuditLog\Middleware\SetAuditContext::class . ':api'
    );

    // Admin routes check 'admin' first, then 'web' as fallback
    $middleware->appendToGroup('web',
        \soullessthread\AuditLog\Middleware\SetAuditContext::class . ':admin,web'
    );
})

// In a route group
Route::middleware(['auth:admin', SetAuditContext::class . ':admin'])->group(function () {
    // audit logs will carry the admin's user_id and user_type
});

// config/audit-log.php
return [
    'default_table'          => 'audit_logs',
    'connection'             => env('DB_CONNECTION', 'mysql'),
    'model_paths'            => [app_path('Models')],
    'global_exclude_columns' => ['created_at', 'updated_at', 'deleted_at', 'remember_token'],
    'sensitive_columns'      => ['password', 'password_hash', 'secret', 'token', 'api_key', 'api_secret'],
    'retention_days'         => 365,

    // Guards checked in order; first authenticated user wins.
    // Override per-route with the middleware parameter (see below).
    'auth_guards'            => [],   // [] = default guard only

    'context_extras'         => null,
];
bash
php artisan vendor:publish --tag=audit-log-config
php artisan vendor:publish --tag=audit-log-migrations
php artisan migrate
bash
php artisan audit:sync
bash
php artisan audit:sync
php artisan audit:sync --model="App\Models\Invoice"
php artisan audit:sync --dry-run
php artisan audit:sync --connection=secondary
bash
php artisan audit:prune
php artisan audit:prune --days=30
php artisan audit:prune --table=invoice_audit_logs
php artisan audit:prune --all-tables=audit_logs,invoice_audit_logs