A guide to using auditor-bundle.
auditor provides both a query object and a reader to query the full history of any audited entity and even paginate results.
doctrine-provider
The Reader makes it easy to query and retrieve audits from the storage.
It heavily relies on the Query object and takes care of checking roles and auditable state of a given entity.
The Reader takes a provider as the only parameter of its constructor.
Example:
$reader = new Reader($provider);Querying the audits is done by preparing a query and running it.
Creating a query is done by calling Reader::createQuery(string $entity, array $options = []): Query
Example:
$reader = new Reader($provider);
// creates a query on Author audits without any option set
// this would return all the author audits 
$query = $reader->createQuery(Author::class);It is possible to specify filters to be applied to the created query using the $options parameter.
type add a filter on the audit type (INSERT, UPDATE, REMOVE, ASSOCIATE, DISSOCIATE)object_id add a filter on the audited element IDtransaction_hash add a filter on the transaction hashpage will select the given page of entriespage_size defines the page sizeExamples:
$reader = new Reader($provider);
// creates a query on Author audits with a filter on the object ID
// audits of the author which ID is not 5 will be filtered out. 
$query = $reader->createQuery(Author::class, [
    'object_id' => 5,
]);
// the above code could also be written like this
use \DH\Auditor\Provider\Doctrine\Persistence\Reader\Filter\SimpleFilter;
$query = $reader
    ->createQuery(Author::class)
    ->addFilter(new SimpleFilter(Query::OBJECT_ID, 5));
;Once a query has been created and prepared, it has to be executed to retrieve audits.
Example:
$reader = new Reader($provider);
// creates a query on Author audits
$query = $reader->createQuery(Author::class);
// retrieves audit entries for Author entity
/** @var DH\Auditor\Model\Entry[] $audits */
$audits = $query->execute();
// retrieves audit entries for Author entity (oneliner)
/** @var DH\Auditor\Model\Entry[] $audits */
$audits = $reader->createQuery(Author::class)->execute();Note
Retrieving audits using the above method is scoped to a single entity. A transaction generally spans across multiple entities so retrieving audit entries belonging to a transaction could be tough.
To make it easier, a dedicated method is available: Reader::getAuditsByTransactionHash(string $transactionHash): array
Example:
$reader = new Reader($provider);
// retrieves audit entries across all entities for the given transaction hash: '123abc'
/** @var DH\Auditor\Model\Entry[] $audits */
$audits = $reader->getAuditsByTransactionHash('123abc');doctrine-provider
The Query object is a thin wrapper on top of Doctrine's Doctrine\DBAL\Query\QueryBuilder.
It allows to query and retrieve audits from the storage.
The Query object takes both a table name and a connection (Doctrine) as parameters of its constructor.
Example:
// create a Query object to query/retrieve data from `author_audit` table.
$query = new Query('author_audit', $connection);By default, a query object will return all the audit entries of the related table when executed. This can be a very expensive task (both time and memory consuming) and ultimately of little interest. But of course, you can refine the query by adding filters.
There are three types of filters:
You can get the list of available filters by calling Query::getSupportedFilters()
This method will return an array of available filters.
They also are available as constants of the Query class.
Query::TYPE allows to filter by audit type (INSERT, UPDATE, REMOVE, ASSOCIATE, DISSOCIATE)Query::CREATED_AT allows to filter by audit creation date and time Query::TRANSACTION_HASH allows to filter by transaction hashQuery::OBJECT_ID allows to filter by audited element IDQuery::USER_ID allows to filter by userQuery::ID allows to filter by audit IDQuery::DISCRIMINATOR allows to filter by discriminator (cf. Doctrine inheritance)A standard filter is materialized by SimpleFilter class.
Since 1.2.0, method Query::addFilter(string $name, $value): self is deprecated
in favor of Query::addFilter(FilterInterface $filter): self
Examples:
use DH\Auditor\Provider\Doctrine\Persistence\Reader\Filter\SimpleFilter;
// filtering audit entries whose transaction hash is exactly '123abc'
$query = new Query('author_audit', $connection);
$query->addFilter(new SimpleFilter(Query::TRANSACTION_HASH, '123abc'));
// filtering audit entries whose transaction hash is either '123abc', '456def' or '789ghi'
$query = new Query('author_audit', $connection);
$query->addFilter(new SimpleFilter(Query::TRANSACTION_HASH, ['123abc', '456def', '789ghi']));A range filter is materialized by RangeFilter class.
Since 1.2.0, method Query::addRangeFilter(string $name, $minValue = null, $maxValue = null): self is deprecated
in favor of Query::addFilter(FilterInterface $filter): self
Note
Bounds ($minValue and $maxValue) can't be null simultaneously.
Examples:
use DH\Auditor\Provider\Doctrine\Persistence\Reader\Filter\RangeFilter;
// filtering audit entries whose object ID (author ID) is >= 10
$query = new Query('author_audit', $connection);
$query->addFilter(new RangeFilter(Query::OBJECT_ID, 10));
// filtering audit entries whose object ID (author ID) is <= 10
$query = new Query('author_audit', $connection);
$query->addFilter(new RangeFilter(Query::OBJECT_ID, null, 10));
// filtering audit entries whose object ID (author ID) is >= 10 and <= 25
$query = new Query('author_audit', $connection);
$query->addFilter(new RangeFilter(Query::OBJECT_ID, 10, 25));A date range filter is materialized by DateRangeFilter class.
Since 1.2.0, method Query::addDateRangeFilter(string $name, ?DateTime $minValue = null, ?DateTime $maxValue = null): self is deprecated
in favor of Query::addFilter(FilterInterface $filter): self
Note
Bounds ($minValue and $maxValue) can't be null simultaneously.
Examples:
use DH\Auditor\Provider\Doctrine\Persistence\Reader\Filter\DateRangeFilter;
$min = DateTime::createFromFormat('Y-m-d', '2020-01-17');
$max = DateTime::createFromFormat('Y-m-d', '2020-01-19');
// filtering audit entries whose creation date is >= 2020-01-17
$query = new Query('author_audit', $connection);
$query->addFilter(new DateRangeFilter(Query::CREATED_AT, $min));        
// filtering audit entries whose creation date is <= 2020-01-19
$query = new Query('author_audit', $connection);
$query->addFilter(new DateRangeFilter(Query::CREATED_AT, null, $max));  
// filtering audit entries whose creation date is between 2020-01-17 and 2020-01-19
$query = new Query('author_audit', $connection);
$query->addFilter(new DateRangeFilter(Query::CREATED_AT, $min, $max));  When adding multiple filters, they are combined with an and logic. 
Query results can be ordered by calling Query::addOrderBy(string $field, string $direction = 'DESC'): self
Example:
$query = new Query('author_audit', $connection);
$query->addOrderBy(Query::CREATED_AT, 'ASC');
$entries = $query->execute();   // entries are ordered by ascendant creation date/time It is possible to extract only a portion of the results at a specific offset by calling Query::limit(int $limit, int $offset = 0): self
Note
$offset starts at 0.
Example:
// only the first 10 results
$query = new Query('author_audit', $connection);
$query->limit(10);     
// 10 results starting at the 6th result (from the 6th to 15th)
$query = new Query('author_audit', $connection);
$query->limit(10, 5);     Queries are executed by calling Query::execute(): array
Example:
// filtering audit entries whose transaction hash is exactly '123abc'
$query = new Query('author_audit', $connection);
$query->addFilter(Query::TRANSACTION_HASH, '123abc');
$entries = $query->execute();   // $entries is populated It is possible to count results without retrieving them by calling Query::count(): int
Example:
$query = new Query('author_audit', $connection);
$query->addFilter(Query::TRANSACTION_HASH, '123abc');
$count = $query->count();   // $count holds the number of audit entries matching the applied filters