1. Go to this page and download the library: Download ss-ipg/laravel-auditable 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/ */
use SSIPG\Auditable\Attributes\Auditable;
#[Auditable]
class User extends Model
{
// ...
}
// config/auditable.php
return [
// Enable/disable audit logging at runtime
'enabled' => env('AUDITABLE_ENABLED', false),
// Environments where logging is permitted
// Use ['*'] to allow all environments
'environments' => ['local', 'production', 'staging'],
// Log channel name (must exist in config/logging.php)
'channel' => 'audit',
// Context providers for adding custom metadata
'context_providers' => [
// App\Audit\CustomContextProvider::class,
],
// Formatter class for serializing log entries
'formatter' => SSIPG\Auditable\Formatters\JsonFormatter::class,
];
use SSIPG\Auditable\Attributes\Auditable;
use SSIPG\Auditable\Enums\AuditAction;
// Audit everything (default)
#[Auditable]
class User extends Model {}
// Only audit specific columns
#[Auditable(columns: ['email', 'status'])]
class User extends Model {}
// Audit all except certain columns
#[Auditable(exclude: ['cached_data', 'last_seen_at'])]
class User extends Model {}
// Redact sensitive values
#[Auditable(redact: ['password', 'api_key'])]
class User extends Model {}
// Only audit deletions (compliance mode)
#[Auditable(events: [AuditAction::Deleted, AuditAction::SoftDeleted])]
class HighVolumeModel extends Model {}
// Don't track original values on updates (smaller logs)
#[Auditable(withOriginal: false)]
class User extends Model {}
// Combined options
#[Auditable(
columns: ['email', 'password', 'role'],
redact: ['password'],
events: [AuditAction::Updated, AuditAction::Deleted],
withOriginal: false,
)]
class User extends Model {}
// In your model
protected $casts = ['is_active' => 'boolean'];
// These are considered equivalent (no update logged):
$model->is_active = true;
$model->is_active = 1; // Cast to true
$model->is_active = '1'; // Cast to true
namespace App\Audit;
use Illuminate\Database\Eloquent\Model;
use SSIPG\Auditable\Contracts\AuditContextProvider;
use SSIPG\Auditable\Enums\AuditAction;
class CustomContextProvider implements AuditContextProvider
{
public function getContext(Model $model, AuditAction $action): array
{
return [
'custom_id' => $model->custom_id,
];
}
}
namespace App\Audit;
use SSIPG\Auditable\Contracts\AuditFormatter;
class CustomFormatter implements AuditFormatter
{
public function format(array $payload): string
{
// Return your formatted string
return json_encode($payload, JSON_PRETTY_PRINT);
}
}
'formatter' => App\Audit\CustomFormatter::class,
use Illuminate\Database\Eloquent\Relations\Pivot;
use SSIPG\Auditable\Attributes\Auditable;
#[Auditable]
class ProjectUserPivot extends Pivot
{
protected $table = 'project_user';
}
// app/Models/Project.php
public function users(): BelongsToMany
{
return $this->belongsToMany(User::class)->using(ProjectUserPivot::class);
}
// app/Models/User.php
public function projects(): BelongsToMany
{
return $this->belongsToMany(Project::class)->using(ProjectUserPivot::class);
}
use SSIPG\Auditable\Facades\Audit;
use SSIPG\Auditable\Enums\AuditAction;
public function test_user_creation_is_audited(): void
{
Audit::fake();
User::create(['name' => 'John', 'email' => '[email protected]']);
Audit::assertLogged(AuditAction::Created);
}
// Assert an action was logged
Audit::assertLogged(AuditAction::Created);
Audit::assertLogged(AuditAction::Updated);
Audit::assertLogged(AuditAction::Deleted);
Audit::assertLogged(AuditAction::SoftDeleted);
Audit::assertLogged(AuditAction::Restored);
// Assert with callback for detailed matching
Audit::assertLogged(
action: AuditAction::Created,
callback: fn (array $entry) => $entry['model'] === User::class
&& $entry['changes']['email'] === '[email protected]'
);
// Assert an action was NOT logged
Audit::assertNotLogged(AuditAction::Updated);
// Assert nothing was logged
Audit::assertNothingLogged();
// Assert exact count of entries
Audit::assertLoggedCount(2);
// Get all logged entries for inspection
$entries = Audit::logged();
$createdEntries = Audit::logged(AuditAction::Created);
[
'action' => AuditAction::Created, // The action enum
'model' => 'App\\Models\\User', // Model class name
'model_id' => 123, // Model primary key
'changes' => [ // Changed attributes
'name' => 'John',
'email' => '[email protected]',
],
]