Installation:
composer require caxy/audit-log-bundle
Add to config/bundles.php:
return [
// ...
Caxy\AuditLogBundle\CaxyAuditLogBundle::class => ['all' => true],
];
Configure Database:
Update config/packages/doctrine.yaml to include the audit log schema:
doctrine:
orm:
mappings:
CaxyAuditLogBundle: ~
Run migrations:
php bin/console doctrine:migrations:diff
php bin/console doctrine:migrations:migrate
Enable Auditing for an Entity:
Annotate your entity with @AuditLog and define fields to track:
use Caxy\AuditLogBundle\Annotation\AuditLog;
/**
* @AuditLog(fields={"name", "status", "createdAt"})
*/
class Product {}
First Use Case:
Test by creating/updating a Product entity. Check the audit_log table for records:
php bin/console doctrine:query:sql "SELECT * FROM audit_log"
Entity-Level Auditing:
@AuditLog on entities to auto-track changes to specified fields.User profile updates:
/**
* @AuditLog(fields={"email", "role", "lastLogin"})
*/
class User {}
Bulk Operations:
EntityManager::flush()).Soft Deletes:
SoftDeleteable trait to audit deletions:
use Gedmo\SoftDeleteable\Traits\SoftDeleteableEntity;
class Product {
use SoftDeleteableEntity;
// ...
}
deletedAt changes.Custom Actions:
use Caxy\AuditLogBundle\Event\AuditLogEvent;
$event = new AuditLogEvent($entity, 'MANUAL_ACTION', ['note' => 'Custom action']);
$dispatcher->dispatch(AuditLogEvents::AUDIT_LOG, $event);
Symfony Events:
Listen to audit_log.post_persist or audit_log.post_update for post-processing:
# config/services.yaml
services:
App\EventListener\AuditLogListener:
tags:
- { name: kernel.event_listener, event: audit_log.post_persist, method: onAuditLogPersist }
Doctrine Lifecycle Callbacks:
Use prePersist/preUpdate to enrich audit data:
class Product {
public function preUpdate() {
$this->setUpdatedBy($this->getUser()->getId());
}
}
APIs: Expose audit logs via API (e.g., using API Platform):
use ApiPlatform\Core\Annotation\ApiResource;
/**
* @ApiResource()
*/
class AuditLog {}
Performance Overhead:
@AuditLog(ignoreFields={"largeBinaryField"}) to exclude bloated fields.Schema Migrations:
audit_log table exists. Manual schema changes may break it.Circular References:
@ManyToOne) can cause infinite loops.fetch="LAZY" in Doctrine.Symfony 4+ Compatibility:
composer.json to support Symfony 4.4+:
"require": {
"symfony/framework-bundle": "^4.4|^5.0"
}
Missing Logs:
bundles.php.php bin/console debug:event-dispatcher | grep audit
Incorrect Fields:
@AuditLog(fields={...}). Omit fields to exclude them.Timestamp Issues:
updatedAt is missing, ensure Doctrine lifecycle callbacks are set:
use Gedmo\Timestampable\Traits\TimestampableEntity;
class Product {
use TimestampableEntity;
}
Custom Storage:
AuditLogStorage service to log to external systems (e.g., Elasticsearch):
services:
app.audit_log.storage:
class: App\Service\ElasticsearchAuditLogStorage
decorates: caxy_audit_log.storage
Field Transformations:
preAuditLog event to modify payload before storage:
public function onPreAuditLog(AuditLogEvent $event) {
$event->setData(array_merge($event->getData(), ['ip' => $this->getClientIp()]));
}
Access Control:
use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface;
class AuditLogVoter implements VoterInterface {
public function supports(string $attribute, $subject) {
return $attribute === 'VIEW_AUDIT_LOG';
}
}
Bulk Audit Optimization:
$em->flush();
$em->getConnection()->beginTransaction();
// Batch audit logs here
$em->getConnection()->commit();
---
How can I help you explore Laravel packages today?