Custom Events

Standard CRUD events are captured automatically, but your application has domain-specific events too — an order shipped, a document published, an account locked. The audit() method lets you record these directly on the model.

Basic Usage

Call audit() on any auditable model with an event name:

$order->audit('shipped');
$document->audit('published');
$account->audit('locked');

This creates an audit log entry with your custom event name, the current user, IP address, and timestamp.

With Old and New Values

For events that represent a state change, pass oldValues and newValues:

$order->audit('status_changed',
    oldValues: ['status' => 'pending'],
    newValues: ['status' => 'shipped'],
);
$user->audit('role_upgraded',
    oldValues: ['role' => 'editor'],
    newValues: ['role' => 'admin'],
);

These values are stored exactly as provided — AuditChain does not infer them from the model's attributes.

How It Works

Custom events follow the same pipeline as automatic events:

  • The authenticated user, IP address, and user agent are captured
  • The current batch UUID and context are attached
  • If withoutAudit() is active, the event is silently skipped
  • In full mode (HasAuditTrail), the entry is added to the hash chain

Combining with Model Updates

A custom event and a model update are separate audit log entries. Use batch grouping to link them:

use GrayMatter\AuditChain\Facades\AuditChain;

AuditChain::batch(function () use ($order) {
    $order->audit('status_changed',
        oldValues: ['status' => 'pending'],
        newValues: ['status' => 'shipped'],
    );
    $order->update(['status' => 'shipped']);
});

Both entries share the same batch_uuid, making it clear they belong to the same operation.

Querying Custom Events

$order->auditLogs()->where('event', 'shipped')->get();
$order->auditLogs()->whereNotIn('event', ['created', 'updated', 'deleted'])->get();