Installation
composer require drjele/doctrine-audit
Ensure your project uses Doctrine ORM (v2.5+).
Configuration
Add the bundle to config/bundles.php (Symfony) or register the service provider in config/app.php (Laravel via doctrine/orm bridge):
// Laravel (if using Symfony components)
$provider = new \DrJele\DoctrineAudit\DoctrineAuditBundle();
$this->registerServiceProvider($provider);
First Audit
Enable auditing for an entity (e.g., User):
use DrJele\DoctrineAudit\Annotation as ORMAudit;
/**
* @ORM\Entity
* @ORMAudit\Audit
*/
class User { ... }
Or via YAML/XML if using annotations.
Trigger Audits
Doctrine events (prePersist, preUpdate, preRemove) automatically log changes. Verify with:
$auditLog = $entityManager->getRepository(AuditLog::class)->findBy(['entity' => User::class]);
Annotate Entities
Use @Audit on entities and @AuditField on properties to specify tracked fields:
/**
* @ORMAudit\AuditField(fieldName="email", fieldType="string")
*/
private $email;
Customize Audit Metadata
Override default metadata (e.g., auditTable, logEntity) via:
# config/packages/drjele_doctrine_audit.yaml
drjele_doctrine_audit:
audit_table: 'custom_audit_logs'
log_entity: App\Entity\CustomAuditLog
Query Audits Fetch changes for a specific entity:
$audits = $entityManager->getRepository(AuditLog::class)
->findBy(['entityClass' => User::class, 'field' => 'email']);
Soft-Deletes
Extend AuditLog to include soft-delete logic:
use DrJele\DoctrineAudit\Model\AuditLog as BaseAuditLog;
class AuditLog extends BaseAuditLog {
public function isDeleted(): bool { ... }
}
doctrine/orm via spatie/laravel-doctrine-orm for seamless integration.postAudit events:
$eventManager->addEventListener(
Events::POST_AUDIT,
[$this, 'onPostAudit']
);
$entityManager->getConnection()->getConfiguration()->setSQLLogger(null);
Performance Overhead
@AuditField selectively.auditIgnoreFields.Entity Manager Scope
EntityManager. Ensure the same EM is used across transactions.Annotation Conflicts
@ORM\Column) may clash with @AuditField.@DrJele\DoctrineAudit\Annotation\AuditField).Missing Audit Logs
@Audit.AuditLog entity is mapped (check drjele_doctrine_audit.log_entity).DoctrineAuditBundle registration).$entityManager->getConnection()->getConfiguration()->setSQLLogger(new \Doctrine\DBAL\Logging\EchoSQLLogger());
DoctrineAuditBundle's services.yaml for registered listeners.Custom Audit Log
Extend AuditLog to add fields (e.g., ipAddress):
class CustomAuditLog extends AuditLog {
/**
* @ORM\Column(type="string", nullable=true)
*/
private $ipAddress;
}
Update drjele_doctrine_audit.log_entity to point to CustomAuditLog.
Dynamic Field Auditing Use a listener to audit fields conditionally:
public function onPreFlush(PreFlushEventArgs $args) {
$entity = $args->getEntity();
if ($entity instanceof User && $entity->isSensitiveUpdate()) {
$args->getObjectManager()->getEventManager()->addEventListener(
Events::PRE_UPDATE,
[$this, 'auditSensitiveFields']
);
}
}
Asynchronous Auditing Offload audits to a queue (e.g., Symfony Messenger) to avoid blocking writes:
$eventDispatcher->dispatch(new AuditEvent($entity, $action), Events::POST_AUDIT);
How can I help you explore Laravel packages today?