PHP code example of iamfarhad / laravel-audit-log

1. Go to this page and download the library: Download iamfarhad/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/ */

    

iamfarhad / laravel-audit-log example snippets


return [
    // Default audit driver
    'default' => env('AUDIT_DRIVER', 'mysql'),

    // Driver-specific configurations
    'drivers' => [
        'mysql' => [
            'connection' => env('AUDIT_MYSQL_CONNECTION', config('database.default')),
            'table_prefix' => env('AUDIT_TABLE_PREFIX', 'audit_'),
            'table_suffix' => env('AUDIT_TABLE_SUFFIX', '_logs'),
        ],
    ],

    // Queue processing configuration
    'queue' => [
        'enabled' => env('AUDIT_QUEUE_ENABLED', false),
        'connection' => env('AUDIT_QUEUE_CONNECTION', config('queue.default')),
        'queue_name' => env('AUDIT_QUEUE_NAME', 'audit'),
        'delay' => env('AUDIT_QUEUE_DELAY', 0),
    ],

    // Enable automatic migration for audit tables
    'auto_migration' => env('AUDIT_AUTO_MIGRATION', true),

    // Enhanced global field exclusions and configuration
    'fields' => [
        'exclude' => [
            'password',
            'remember_token',
            'api_token',
            'email_verified_at',
            'password_hash',
            'secret',
            'token',
            'private_key',
            'access_token',
            'refresh_token',
            'api_key',
            'secret_key',
            'stripe_id',
            'pm_type',
            'pm_last_four',
            'trial_ends_at',
        ],
        '



declare(strict_types=1);

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use iamfarhad\LaravelAuditLog\Traits\Auditable;

final class Order extends Model
{
    use Auditable;

    protected $fillable = ['customer_id', 'total', 'status'];
}

// When a user makes a change via HTTP request
Auth::loginUsingId(1);
$order = Order::create([
    'customer_id' => 123,
    'total' => 99.99,
    'status' => 'pending'
]);

// Audit log will contain:
// - causer_type: "App\Models\User"
// - causer_id: 1
// - source: "App\Http\Controllers\OrderController@store"

// Get audit logs with causer information
$auditLogs = Order::find(1)->auditLogs()
    ->where('causer_type', 'App\Models\User')
    ->where('causer_id', 1)
    ->get();

// Using the EloquentAuditLog model directly
use iamfarhad\LaravelAuditLog\Models\EloquentAuditLog;

$logs = EloquentAuditLog::forEntity(Order::class)
    ->forCauser('App\Models\User')
    ->forCauserId(1)
    ->get();

// Get logs from HTTP requests only
$httpLogs = EloquentAuditLog::forEntity(Order::class)
    ->fromHttp()
    ->get();

// Get logs from console commands only
$consoleLogs = EloquentAuditLog::forEntity(Order::class)
    ->fromConsole()
    ->get();



declare(strict_types=1);

namespace App\Http\Controllers;

use App\Models\Order;
use Illuminate\Http\Request;

final class OrderController extends Controller
{
    public function update(Request $request, Order $order): JsonResponse
    {
        // User is already authenticated via middleware
        // Audit log will automatically capture:
        // - causer_type: "App\Models\User"
        // - causer_id: Auth::id()
        // - source: "App\Http\Controllers\OrderController@update"
        
        $order->update($request->validated());
        
        return response()->json(['success' => true]);
    }
}



declare(strict_types=1);

namespace App\Console\Commands;

use App\Models\Order;
use Illuminate\Console\Command;

final class ProcessOrdersCommand extends Command
{
    protected $signature = 'orders:process';
    
    public function handle(): void
    {
        // For console commands, causer_type and causer_id will be null
        // But source will be: "orders:process"
        
        Order::where('status', 'pending')
            ->each(function ($order) {
                $order->update(['status' => 'processed']);
            });
    }
}



declare(strict_types=1);

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use iamfarhad\LaravelAuditLog\Traits\Auditable;

final class Order extends Model
{
    use Auditable;

    protected $fillable = ['customer_id', 'total', 'status'];

    /**
     * Add user context to audit metadata
     */
    public function getAuditMetadata(): array
    {
        return [
            'ip_address' => request()->ip() ?? 'unknown',
            'user_agent' => request()->userAgent() ?? 'unknown',
            'user_email' => auth()->user()?->email ?? 'system',
            'session_id' => session()->getId() ?? null,
            'request_id' => request()->header('X-Request-Id', 'n/a'),
        ];
    }
}



declare(strict_types=1);

namespace App\Services;

use App\Models\User;
use iamfarhad\LaravelAuditLog\Models\EloquentAuditLog;

final class AuditReportService
{
    public function getUserActivity(User $user, string $action = null): array
    {
        $query = EloquentAuditLog::forCauser(User::class)
            ->forCauserId($user->id)
            ->orderBy('created_at', 'desc');
            
        if ($action) {
            $query->forAction($action);
        }
        
        return $query->get()->map(function ($log) {
            return [
                'entity_type' => $log->entity_type,
                'entity_id' => $log->entity_id,
                'action' => $log->action,
                'source' => $log->source,
                'created_at' => $log->created_at,
                'metadata' => $log->metadata,
            ];
        })->toArray();
    }
    
    public function getHttpRequestChanges(string $controller = null): array
    {
        $query = EloquentAuditLog::fromHttp();
        
        if ($controller) {
            $query->fromController($controller);
        }
        
        return $query->get()->toArray();
    }
    
    public function getConsoleChanges(string $command = null): array
    {
        $query = EloquentAuditLog::fromConsole();
        
        if ($command) {
            $query->fromCommand($command);
        }
        
        return $query->get()->toArray();
    }
}

'causer' => [
    'guard' => null, // null means use default guard, or specify 'api', 'web', etc.
    'model' => null, // null means auto-detect, or specify 'App\Models\CustomUser'
    'resolver' => null, // null means use default resolver, or specify custom class
],



declare(strict_types=1);

namespace App\Services;

use iamfarhad\LaravelAuditLog\Contracts\CauserResolverInterface;
use Illuminate\Support\Facades\Auth;

final class CustomCauserResolver implements CauserResolverInterface
{
    public function resolve(): array
    {
        // Custom logic for resolving the causer
        if (Auth::guard('api')->check()) {
            $user = Auth::guard('api')->user();
            return [
                'type' => get_class($user),
                'id' => $user->id,
            ];
        }
        
        if (Auth::guard('web')->check()) {
            $user = Auth::guard('web')->user();
            return [
                'type' => get_class($user),
                'id' => $user->id,
            ];
        }
        
        // For system operations, you might want to return a system user
        return [
            'type' => 'System',
            'id' => 'system',
        ];
    }
}

// In AppServiceProvider or custom service provider
$this->app->bind(
    \iamfarhad\LaravelAuditLog\Contracts\CauserResolverInterface::class,
    \App\Services\CustomCauserResolver::class
);



declare(strict_types=1);

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use iamfarhad\LaravelAuditLog\Traits\Auditable;

final class User extends Model
{
    use Auditable;

    protected array $auditExclude = [
        'password',
        'remember_token',
        'email_verified_at',
    ];
}



declare(strict_types=1);

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use iamfarhad\LaravelAuditLog\Traits\Auditable;

final class Invoice extends Model
{
    use Auditable;

    protected array $auditInclude = [
        'amount',
        'status',
        'due_date',
    ];
}



declare(strict_types=1);

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use iamfarhad\LaravelAuditLog\Traits\Auditable;

final class Transaction extends Model
{
    use Auditable;

    public function getAuditMetadata(): array
    {
        return [
            'ip_address' => request()->ip() ?? 'unknown',
            'user_agent' => request()->userAgent() ?? 'unknown',
            'request_id' => request()->header('X-Request-Id', 'n/a'),
            'session_id' => session()->getId() ?? null,
        ];
    }
}

// Example audit log entries with source tracking:

// From console command: php artisan app:send-emails
[
    'entity_id' => '1',
    'action' => 'updated',
    'old_values' => '{"email": "[email protected]"}',
    'new_values' => '{"email": "[email protected]"}',
    'source' => 'app:send-emails',
    'created_at' => '2024-01-15 10:30:00'
]

// From HTTP request
[
    'entity_id' => '1', 
    'action' => 'updated',
    'old_values' => '{"status": "pending"}',
    'new_values' => '{"status": "approved"}',
    'source' => 'App\\Http\\Controllers\\OrderController@approve',
    'created_at' => '2024-01-15 10:35:00'
]

// From background job
[
    'entity_id' => '1',
    'action' => 'updated',
    'old_values' => '{"processed": false}',
    'new_values' => '{"processed": true}',
    'source' => 'App\\Jobs\\ProcessPayment',
    'created_at' => '2024-01-15 10:40:00'
]

use iamfarhad\LaravelAuditLog\Models\EloquentAuditLog;

// Find all changes made by a specific console command
$commandLogs = EloquentAuditLog::forEntity(User::class)
    ->fromCommand('app:send-emails')
    ->get();

// Find all changes made through console commands
$consoleLogs = EloquentAuditLog::forEntity(User::class)
    ->fromConsole()
    ->get();

// Find all changes made through HTTP requests
$webLogs = EloquentAuditLog::forEntity(User::class)
    ->fromHttp()
    ->get();

// Find changes from a specific controller
$controllerLogs = EloquentAuditLog::forEntity(User::class)
    ->fromController('UserController')
    ->get();

// Find changes by exact source match
$exactSourceLogs = EloquentAuditLog::forEntity(User::class)
    ->forSource('app:send-emails')
    ->get();

// Complex filtering with multiple scopes
$filteredLogs = EloquentAuditLog::forEntity(User::class)
    ->fromConsole()
    ->forAction('updated')
    ->dateBetween(now()->subWeek(), now())
    ->forCauserId(1)
    ->orderBy('created_at', 'desc')
    ->paginate(20);

$user = User::find(1);
$user->disableAuditing();
$user->update(['email' => '[email protected]']); // This change won't be logged
$user->enableAuditing();



declare(strict_types=1);

use App\Models\Order;

$order = Order::find(1);
$order->audit()
    ->custom('status_transition')
    ->from(['status' => 'pending', 'previous_state' => 'draft'])
    ->to(['status' => 'shipped', 'tracking_number' => 'TRK123456'])
    ->withMetadata([
        'ip' => request()->ip(),
        'user_agent' => request()->userAgent(),
        'reason' => 'Automatic shipment processing',
        'batch_id' => 'BATCH_001'
    ])
    ->log();

// config/audit-logger.php
'queue' => [
    'enabled' => true,
    'connection' => 'redis', // or your preferred queue connection
    'queue_name' => 'audit',
    'delay' => 0, // delay in seconds before processing
],



declare(strict_types=1);

namespace App\Audit\Drivers;

use iamfarhad\LaravelAuditLog\Contracts\AuditDriverInterface;
use iamfarhad\LaravelAuditLog\DTOs\AuditLog;

final class CustomAuditDriver implements AuditDriverInterface
{
    public function log(AuditLog $auditLog): void
    {
        // Your custom logging implementation
    }

    public function createStorageForEntity(string $entityClass): void
    {
        // Your custom storage creation logic
    }

    // ... implement other 



declare(strict_types=1);

namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use iamfarhad\LaravelAuditLog\Contracts\AuditDriverInterface;
use App\Audit\Drivers\CustomAuditDriver;

final class AuditServiceProvider extends ServiceProvider
{
    public function register(): void
    {
        $this->app->bind(AuditDriverInterface::class, CustomAuditDriver::class);
    }
}



declare(strict_types=1);

namespace App\Audit;

use iamfarhad\LaravelAuditLog\Contracts\CauserResolverInterface;
use Illuminate\Database\Eloquent\Model;

final class CustomCauserResolver implements CauserResolverInterface
{
    public function resolve(): ?Model
    {
        // Your custom causer resolution logic
        return auth()->user() ?? $this->getSystemUser();
    }

    private function getSystemUser(): ?Model
    {
        // Return a system user for automated processes
        return User::where('email', '[email protected]')->first();
    }
}

$user = User::find(1);

// Retrieve all audit logs
$allLogs = $user->auditLogs()->get();

// Filter by specific action
$updateLogs = $user->auditLogs()->where('action', 'updated')->get();

// Get the most recent logs with pagination
$recentLogs = $user->auditLogs()
    ->orderBy('created_at', 'desc')
    ->paginate(10);

// Include metadata and causer information
$detailedLogs = $user->auditLogs()
    ->with(['causer'])
    ->orderBy('created_at', 'desc')
    ->get();



declare(strict_types=1);

use iamfarhad\LaravelAuditLog\Models\EloquentAuditLog;

// Basic entity filtering
$logs = EloquentAuditLog::forEntity(User::class)
    ->forEntityId(1)
    ->orderBy('created_at', 'desc')
    ->get();

// Complex multi-criteria filtering
$filteredLogs = EloquentAuditLog::forEntity(Order::class)
    ->forAction('updated')
    ->forCauserId(1)
    ->fromCommand('app:process-orders')
    ->dateBetween(now()->subWeek(), now())
    ->orderBy('created_at', 'desc')
    ->paginate(20);

// Source-specific queries
$consoleLogs = EloquentAuditLog::forEntity(User::class)
    ->fromConsole()
    ->dateGreaterThan(now()->subHour())
    ->get();

$controllerLogs = EloquentAuditLog::forEntity(Order::class)
    ->fromController('OrderController')
    ->forAction(['created', 'updated'])
    ->get();

// Aggregation and analytics
$dailyStats = EloquentAuditLog::forEntity(User::class)
    ->selectRaw('DATE(created_at) as date, action, COUNT(*) as count')
    ->dateBetween(now()->subMonth(), now())
    ->groupBy('date', 'action')
    ->orderBy('date', 'desc')
    ->get();

// config/audit-logger.php
return [
'queue' => [
    'enabled' => true,
        'connection' => 'redis',
    'queue_name' => 'audit',
    ],
    'fields' => [
        'exclude' => [
            // Add non-critical fields to reduce storage
            'updated_at',
            'last_activity',
            'view_count',
        ],
        '

// Example service for audit log maintenance


declare(strict_types=1);

namespace App\Services;

use iamfarhad\LaravelAuditLog\Models\EloquentAuditLog;

final class AuditMaintenanceService
{
    public function cleanupOldLogs(int $daysToKeep = 365): int
    {
        return EloquentAuditLog::where('created_at', '<', now()->subDays($daysToKeep))
            ->delete();
    }

    public function getStorageStats(): array
    {
        return [
            'total_logs' => EloquentAuditLog::count(),
            'logs_last_30_days' => EloquentAuditLog::dateGreaterThan(now()->subDays(30))->count(),
            'most_active_entities' => EloquentAuditLog::selectRaw('entity_type, COUNT(*) as count')
                ->groupBy('entity_type')
                ->orderBy('count', 'desc')
                ->limit(10)
                ->get(),
        ];
    }
}



declare(strict_types=1);

namespace Tests\Feature;

use Tests\TestCase;
use App\Models\User;
use iamfarhad\LaravelAuditLog\Models\EloquentAuditLog;

final class UserAuditTest extends TestCase
{
    public function test_user_creation_is_audited(): void
    {
        $user = User::create([
            'name' => 'John Doe',
            'email' => '[email protected]',
        ]);

        $this->assertDatabaseHas('audit_users_logs', [
            'entity_id' => $user->id,
            'action' => 'created',
        ]);

        $auditLog = EloquentAuditLog::forEntity(User::class)
            ->forEntityId($user->id)
            ->forAction('created')
            ->first();

        $this->assertNotNull($auditLog);
        $this->assertEquals('created', $auditLog->action);
        $this->assertNotNull($auditLog->new_values);
    }

    public function test_sensitive_fields_are_excluded(): void
    {
        $user = User::create([
            'name' => 'John Doe',
            'email' => '[email protected]',
            'password' => bcrypt('secret'),
        ]);

        $auditLog = EloquentAuditLog::forEntity(User::class)
            ->forEntityId($user->id)
            ->first();

        $newValues = json_decode($auditLog->new_values, true);
        $this->assertArrayNotHasKey('password', $newValues);
    }
}

// Example policy for audit log access


declare(strict_types=1);

namespace App\Policies;

use App\Models\User;
use Illuminate\Auth\Access\HandlesAuthorization;

final class AuditLogPolicy
{
    use HandlesAuthorization;

    public function viewAny(User $user): bool
    {
        return $user->hasPermission('audit.view');
    }

    public function view(User $user, string $entityType, $entityId): bool
    {
        return $user->hasPermission('audit.view') 
            && $this->canAccessEntity($user, $entityType, $entityId);
    }

    private function canAccessEntity(User $user, string $entityType, $entityId): bool
    {
        // Implement your business logic for entity access
        return true;
    }
}

'retention' => [
    'enabled' => env('AUDIT_RETENTION_ENABLED', false),
    'days' => env('AUDIT_RETENTION_DAYS', 365),
    'strategy' => env('AUDIT_RETENTION_STRATEGY', 'delete'), // 'delete', 'archive', 'anonymize'
    'batch_size' => env('AUDIT_RETENTION_BATCH_SIZE', 1000),
    'anonymize_after_days' => env('AUDIT_ANONYMIZE_DAYS', 180),
    'archive_connection' => env('AUDIT_ARCHIVE_CONNECTION', null),
    'run_cleanup_automatically' => env('AUDIT_AUTO_CLEANUP', false),
],

'entities' => [
    \App\Models\User::class => [
        'table' => 'users',
        'retention' => [
            'enabled' => true,
            'days' => 730, // Keep for 2 years
            'strategy' => 'anonymize',
            'anonymize_after_days' => 365, // Anonymize after 1 year
        ],
    ],
    \App\Models\Order::class => [
        'table' => 'orders',
        'retention' => [
            'days' => 2555, // Keep for 7 years (compliance)
            'strategy' => 'archive',
        ],
    ],
],



declare(strict_types=1);

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use iamfarhad\LaravelAuditLog\Traits\Auditable;

final class User extends Model
{
    use Auditable;

    // Per-model retention configuration
    protected array $auditRetention = [
        'enabled' => true,
        'days' => 730,
        'strategy' => 'anonymize',
        'anonymize_after_days' => 365,
    ];
}

'strategy' => 'delete',
'days' => 365, // Delete records older than 1 year

'strategy' => 'anonymize',
'days' => 180, // Anonymize records older than 6 months

'strategy' => 'archive',
'days' => 365, // Archive records older than 1 year
'archive_connection' => 'archive_db',

'strategy' => 'delete', // or 'archive'
'days' => 730, // Final action after 2 years
'anonymize_after_days' => 365, // Anonymize after 1 year

use iamfarhad\LaravelAuditLog\Jobs\RetentionCleanupJob;

// Dispatch cleanup job for all entities
RetentionCleanupJob::dispatch();

// Dispatch cleanup job for specific entity  
RetentionCleanupJob::dispatch('App\Models\User');

protected function schedule(Schedule $schedule): void
{
    // Run retention cleanup weekly
    $schedule->command('audit:cleanup --force')
        ->weekly()
        ->environments(['production']);
    
    // Or run for specific entities
    $schedule->command('audit:cleanup --entity="App\Models\User" --force')
        ->daily()
        ->at('02:00');
}



declare(strict_types=1);

use iamfarhad\LaravelAuditLog\Contracts\RetentionServiceInterface;
use iamfarhad\LaravelAuditLog\DTOs\RetentionConfig;

final class AuditMaintenanceService
{
    public function __construct(
        private readonly RetentionServiceInterface $retentionService
    ) {}

    public function cleanupUserAudits(): void
    {
        $config = new RetentionConfig(
            enabled: true,
            days: 365,
            strategy: 'anonymize',
            batchSize: 1000,
            anonymizeAfterDays: 180
        );

        $result = $this->retentionService->processRetention(
            entityClass: 'App\Models\User',
            config: $config,
            dryRun: false
        );

        // Handle results...
    }
}

// In your service provider or configuration
use iamfarhad\LaravelAuditLog\Services\AuditLogger;

// Enable debug mode (not recommended for production)
AuditLogger::enableDebugMode();

// This will log additional information about audit processing
bash
php artisan vendor:publish --tag=audit-logger-config
bash
   php artisan vendor:publish --tag=audit-logger-config --force