Skip to content

Commit bb0f06c

Browse files
author
farhadzand
committed
new structure
1 parent 2a3bc18 commit bb0f06c

18 files changed

+342
-223
lines changed

.gitattributes

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
/.github export-ignore
66
/.gitattributes export-ignore
77
/.gitignore export-ignore
8+
/.scrutinizer.yml export-ignore
89
/phpunit.xml.dist export-ignore
910
/pint.json export-ignore
1011
/phpstan.neon export-ignore

CHANGELOG.md

Lines changed: 0 additions & 44 deletions
This file was deleted.

README.md

Lines changed: 125 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,13 @@
1111
[![Tests](https://img.shields.io/github/actions/workflow/status/iamfarhad/laravel-audit-log/tests.yml?branch=main&label=tests&style=flat-square)](https://github.com/iamfarhad/laravel-audit-log/actions/workflows/tests.yml)
1212
[![Code Style](https://img.shields.io/github/actions/workflow/status/iamfarhad/laravel-audit-log/coding-standards.yml?branch=main&label=code%20style&style=flat-square)](https://github.com/iamfarhad/laravel-audit-log/actions/workflows/coding-standards.yml)
1313
[![PHPStan](https://img.shields.io/badge/PHPStan-level%208-brightgreen.svg?style=flat-square)](https://github.com/iamfarhad/laravel-audit-log)
14+
[![Scrutinizer Code Quality](https://img.shields.io/scrutinizer/g/iamfarhad/laravel-audit-log.svg?style=flat-square)](https://scrutinizer-ci.com/g/iamfarhad/laravel-audit-log)
1415

1516
## Overview
1617

17-
**Laravel Audit Logger** is a powerful and flexible package designed to provide detailed audit logging for Laravel applications. It enables tracking of all changes to your Eloquent models, ensuring compliance with regulatory requirements, aiding in debugging, and maintaining data integrity. Built with modern PHP and Laravel practices, this package adheres to strict typing, PSR-12 coding standards, and leverages dependency injection for maximum testability and maintainability.
18+
**Laravel Audit Logger** is a powerful and flexible package designed to provide detailed audit logging for Laravel applications. It enables tracking of all changes to your Eloquent models with comprehensive source tracking, ensuring compliance with regulatory requirements, aiding in debugging, and maintaining data integrity. Built with modern PHP and Laravel practices, this package adheres to strict typing, PSR-12 coding standards, and leverages dependency injection for maximum testability and maintainability.
19+
20+
The package uses a high-performance direct logging architecture while maintaining flexibility through optional event integration, making it suitable for both small applications and enterprise-scale systems.
1821

1922
## Table of Contents
2023

@@ -25,6 +28,7 @@
2528
- [Usage](#usage)
2629
- [Basic Usage](#basic-usage)
2730
- [Advanced Usage](#advanced-usage)
31+
- [Source Tracking](#source-tracking)
2832
- [Customizing Audit Logging](#customizing-audit-logging)
2933
- [Retrieving Audit Logs](#retrieving-audit-logs)
3034
- [Performance Optimization](#performance-optimization)
@@ -38,9 +42,10 @@
3842

3943
- **Entity-Specific Audit Tables**: Automatically creates dedicated tables for each audited model to optimize performance and querying.
4044
- **Comprehensive Change Tracking**: Logs all CRUD operations (create, update, delete, restore) with old and new values.
45+
- **Source Tracking**: Automatically tracks the source of changes (console commands, HTTP routes, etc.) for enhanced debugging and compliance.
4146
- **Customizable Field Logging**: Control which fields to include or exclude from auditing.
4247
- **User Tracking**: Automatically identifies and logs the user (causer) responsible for changes.
43-
- **Event-Driven Architecture**: Utilizes Laravel Events for decoupled and extensible audit logging.
48+
- **Direct Logging Architecture**: Uses direct service calls for high-performance, synchronous audit logging with optional event integration.
4449
- **Batch Processing**: Supports batch operations for high-performance logging in large-scale applications.
4550
- **Type Safety**: Built with PHP 8.1+ strict typing and modern features like `readonly` properties and enums.
4651
- **Extensible Drivers**: Supports multiple storage drivers (currently MySQL) with the ability to implement custom drivers.
@@ -115,6 +120,35 @@ return [
115120

116121
Ensure you review and adjust these settings based on your application's needs, especially for sensitive data exclusion and performance optimization.
117122

123+
### Database Schema
124+
125+
The audit logger creates tables with the following structure for each audited model:
126+
127+
```sql
128+
CREATE TABLE audit_{model_name}_logs (
129+
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
130+
entity_id VARCHAR(255) NOT NULL,
131+
action VARCHAR(255) NOT NULL,
132+
old_values JSON NULL,
133+
new_values JSON NULL,
134+
causer_type VARCHAR(255) NULL,
135+
causer_id VARCHAR(255) NULL,
136+
metadata JSON NULL,
137+
created_at TIMESTAMP NOT NULL,
138+
source VARCHAR(255) NULL,
139+
140+
INDEX idx_entity_id (entity_id),
141+
INDEX idx_causer (causer_type, causer_id),
142+
INDEX idx_created_at (created_at),
143+
INDEX idx_source (source)
144+
);
145+
```
146+
147+
The `source` field is automatically populated to track the origin of changes:
148+
- Console commands: Command name (e.g., `app:send-emails`)
149+
- HTTP requests: Controller action (e.g., `App\Http\Controllers\UserController@update`)
150+
- Background jobs: Job class name
151+
118152
## Usage
119153

120154
### Basic Usage
@@ -223,6 +257,55 @@ final class Transaction extends Model
223257
}
224258
```
225259

260+
#### Source Tracking
261+
262+
The audit logger automatically tracks the source of changes to help with debugging and compliance. The source field captures:
263+
264+
- **Console Commands**: Artisan command names (e.g., `app:send-emails`, `migrate`, `queue:work`)
265+
- **HTTP Routes**: Controller action names or route names for web requests
266+
- **Background Jobs**: Job class names when changes occur within queued jobs
267+
268+
```php
269+
// Example audit log entries with source tracking:
270+
271+
// From console command: php artisan app:send-emails
272+
[
273+
'entity_id' => '1',
274+
'action' => 'updated',
275+
'old_values' => '{"email": "[email protected]"}',
276+
'new_values' => '{"email": "[email protected]"}',
277+
'source' => 'app:send-emails',
278+
'created_at' => '2024-01-15 10:30:00'
279+
]
280+
281+
// From HTTP request
282+
[
283+
'entity_id' => '1',
284+
'action' => 'updated',
285+
'old_values' => '{"status": "pending"}',
286+
'new_values' => '{"status": "approved"}',
287+
'source' => 'App\\Http\\Controllers\\OrderController@approve',
288+
'created_at' => '2024-01-15 10:35:00'
289+
]
290+
```
291+
292+
You can query audit logs by source to track changes from specific commands or controllers:
293+
294+
```php
295+
use iamfarhad\LaravelAuditLog\Models\EloquentAuditLog;
296+
297+
// Find all changes made by a specific console command
298+
$commandLogs = EloquentAuditLog::where('source', 'app:send-emails')->get();
299+
300+
// Find all changes made through web interface
301+
$webLogs = EloquentAuditLog::where('source', 'like', 'App\\Http\\Controllers\\%')->get();
302+
303+
// Find changes from console commands
304+
$consoleLogs = EloquentAuditLog::whereNotNull('source')
305+
->where('source', 'not like', 'App\\Http\\Controllers\\%')
306+
->get();
307+
```
308+
226309
#### Temporarily Disabling Auditing
227310

228311
For specific operations where auditing is not required, you can disable it temporarily:
@@ -236,7 +319,25 @@ $user->enableAuditing();
236319

237320
#### Custom Audit Events
238321

239-
To log custom actions beyond standard CRUD operations, dispatch the `ModelAudited` event manually:
322+
To log custom actions beyond standard CRUD operations, use the fluent API provided by the `audit()` method for direct, high-performance logging:
323+
324+
```php
325+
<?php
326+
327+
declare(strict_types=1);
328+
329+
use App\Models\Order;
330+
331+
$order = Order::find(1);
332+
$order->audit()
333+
->custom('status_changed')
334+
->from(['status' => 'pending'])
335+
->to(['status' => 'shipped'])
336+
->withMetadata(['ip' => request()->ip(), 'user_agent' => request()->userAgent()])
337+
->log();
338+
```
339+
340+
Alternatively, you can still use the traditional event-driven approach if needed:
240341

241342
```php
242343
<?php
@@ -354,10 +455,22 @@ $adminLogs = EloquentAuditLog::forEntity(User::class)
354455
->where('entity_id', 1)
355456
->get();
356457

458+
// Filter by source (console commands, HTTP routes, etc.)
459+
$consoleLogs = EloquentAuditLog::forEntity(User::class)
460+
->where('source', 'app:send-emails')
461+
->where('entity_id', 1)
462+
->get();
463+
464+
$webLogs = EloquentAuditLog::forEntity(User::class)
465+
->where('source', 'like', 'App\\Http\\Controllers\\%')
466+
->where('entity_id', 1)
467+
->get();
468+
357469
// Combine multiple scopes for precise filtering
358470
$filteredLogs = EloquentAuditLog::forEntity(User::class)
359471
->action('updated')
360472
->causer(1)
473+
->where('source', 'app:send-emails')
361474
->dateBetween(now()->subDays(7), now())
362475
->where('entity_id', 1)
363476
->orderBy('created_at', 'desc')
@@ -400,6 +513,15 @@ When writing tests for your application, ensure you cover audit logging behavior
400513
- **Audit Tables Not Created**: Ensure `'auto_migration' => true` in your configuration. If disabled, manually create tables using `AuditLogger::driver()->createStorageForEntity(Model::class)`.
401514
- **Missing Logs**: Verify that fields aren't excluded globally or in the model, and ensure auditing isn't disabled for the operation.
402515
- **Causer Not Recorded**: Confirm that authentication is set up correctly and the user is logged in during the operation.
516+
- **Source Field Empty**: The source field should automatically populate. If it's null, check that:
517+
- For console commands: `$_SERVER['argv']` is available and contains the command name
518+
- For HTTP requests: The route is properly registered and accessible via `Request::route()`
519+
- The application is running in the expected context (console vs. HTTP)
520+
- **Migration Issues**: If upgrading from a previous version, ensure your existing audit tables include the `source` column. You may need to add it manually:
521+
```sql
522+
ALTER TABLE audit_your_model_logs ADD COLUMN source VARCHAR(255) NULL;
523+
CREATE INDEX idx_source ON audit_your_model_logs (source);
524+
```
403525

404526
## Contributing
405527

src/Contracts/AuditLogInterface.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,11 @@ public function getMetadata(): array;
5353
*/
5454
public function getCreatedAt(): DateTimeInterface;
5555

56+
/**
57+
* Get the source of the audit log.
58+
*/
59+
public function getSource(): ?string;
60+
5661
/**
5762
* Convert to array representation.
5863
*/

src/DTOs/AuditLog.php

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ public function __construct(
1919
private readonly ?string $causerType,
2020
private readonly string|int|null $causerId,
2121
private readonly array $metadata,
22-
private readonly DateTimeInterface $createdAt
22+
private readonly DateTimeInterface $createdAt,
23+
private readonly ?string $source
2324
) {}
2425

2526
public function getEntityType(): string
@@ -67,6 +68,11 @@ public function getCreatedAt(): DateTimeInterface
6768
return $this->createdAt;
6869
}
6970

71+
public function getSource(): ?string
72+
{
73+
return $this->source;
74+
}
75+
7076
public function toArray(): array
7177
{
7278
return [
@@ -81,6 +87,7 @@ public function toArray(): array
8187
'created_at' => $this->createdAt instanceof Carbon
8288
? $this->createdAt->toIso8601String()
8389
: $this->createdAt->format(DateTimeInterface::ATOM),
90+
'source' => $this->source,
8491
];
8592
}
8693

@@ -100,7 +107,8 @@ public static function fromArray(array $data): self
100107
metadata: $data['metadata'] ?? [],
101108
createdAt: $data['created_at'] instanceof DateTimeInterface
102109
? $data['created_at']
103-
: Carbon::parse($data['created_at'])
110+
: Carbon::parse($data['created_at']),
111+
source: $data['source'] ?? null,
104112
);
105113
}
106114
}

src/Drivers/MySQLDriver.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
namespace iamfarhad\LaravelAuditLog\Drivers;
66

77
use Illuminate\Support\Str;
8+
use Illuminate\Support\Facades\Log;
89
use Illuminate\Support\Facades\Schema;
910
use Illuminate\Database\Schema\Blueprint;
1011
use iamfarhad\LaravelAuditLog\Models\EloquentAuditLog;
@@ -46,6 +47,7 @@ public function store(AuditLogInterface $log): void
4647
'causer_id' => $log->getCauserId(),
4748
'metadata' => json_encode($log->getMetadata()),
4849
'created_at' => $log->getCreatedAt(),
50+
'source' => $log->getSource(),
4951
]);
5052
$model->save();
5153
} catch (\Exception $e) {
@@ -83,6 +85,7 @@ public function createStorageForEntity(string $entityClass): void
8385
$table->string('causer_id')->nullable();
8486
$table->json('metadata')->nullable();
8587
$table->timestamp('created_at');
88+
$table->string('source')->nullable();
8689

8790
$table->index('entity_id');
8891
$table->index('causer_id');

src/Events/ModelAudited.php

Lines changed: 0 additions & 24 deletions
This file was deleted.

0 commit comments

Comments
 (0)