Internals

This document describes how auditing works in the code, internal to the application.

There are four primary actions which zf-doctrine-audit implements. The first is building an audit database based on the configuration listing entities and joinEntities.

Audit Entity Autoloader

In order to map configured entities to a database we must have a class for each audited entity. The naming of these classes follows this pattern (found in ZF\Doctrine\Audit\Repository\AuditEntityRepository):

return "ZF\\Doctrine\\Audit\\RevisionEntity\\" . str_replace('\\', '_', $entityName);

So an entity in the target object manager named Db\Entity\User will be audited by an entity in the audit object manager named ZF\\Doctrine\\Audit\\RevisionEntity\\Db_Entity_User. Access to this entity through the audit object manager works as you would expect in a doctrine object manager:

$auditObjectManger->getRepository('ZF\\Doctrine\\Audit\\RevisionEntity\\Db_Entity_User')
    ->findBy([
        'id' => 2,
    ]);

This code will fetch the complete audit history for the Db\Entity\User entity with id = 2.

This is possible because audit entity classes are dynamically created via an Autoloader.

Audit Object Manager Metadata

Mapping drivers for configured entities and joinEntities dynamically create metadata based on target entity metadata. By introspecting the existing target entity metadata a new metadata definition can be assigned to an Autoloader created class.

The dynamically created classes assigned to dynamically created metadata combined with static auditing entities creates a complete audit object manager in the application. This object manager can be used by the schema tool and that is how the audit database is created.

Trigger Tool

Currently zf-doctrine-audit only supports MySQL. However the code is written such that new databases may be supported. The SQL for the target database is generated by the Trigger Tool. This tool implements two functions:

get_revision_entity_audit
close_revision_audit

get_revision_entity_audit function

get_revision_entity_audit will create a new record in the RevisionEntity_Audit table and possibly the Revision_Audit table. When get_revision_entity_audit is called a check is done if a Revision_Audit record exists with the current connectionId. If found the id for that record is used. This allows multiple sql calls to be grouped into a single Revision.

Grouping of multiple sql calls into a single Revision only happens when running through the Object Manager. When changes are made to the target database through another means each Revision has only one RevisionEntity.

get_revision_entity_audit returns an id for a newly created RevisionEntity_Audit record. This id is assigned to the auditing table audit row.

close_revision_audit function

When running through an ORM this function is called postFlush. The Revision Comment comment is passed to the function along with the authenticated user. This changes the connectionId back to null. While the connectionId is not null it is used to group RevisionEntity together.

When running from a command line or attaching to the database is any other way than through the ORM this function is called at the end of each table create, update, and delete trigger.

create, update, delete triggers

Every table which is audited is assinged three triggers, one each for create, update, and delete. These triggers copy the audited row data into the audit database, assign a RevisionEntity, and either call close_revision_audit or not.

The create trigger populates the audit table with the new data. The update trigger populates the audit table with the new, updated, data. The delete trigger populates the audit table with the last data for the row. In other words, the last update audit data will match the delete audit data.

Epoch Tool

This tool creates temporary stored procedures, runs them, then deletes them. This method is the fastest way to copy data from the target database into the audit database. The stored procedures output status information while they work.

RevisionAudit Tool

This tool is responsible for closing the Revision_Audit table after changes have been made. This tool can be called on its own. This tool is called in postFlush().