1. Go to this page and download the library: Download yahyaerturan/audit library. Choose the download type require.
2. Extract the ZIP file and open the index.php.
3. Add this code to the index.php.
<?php
require_once('vendor/autoload.php');
/* Start to develop here. Best regards https://php-download.com/ */
yahyaerturan / audit example snippets
use YahyaErturan\Audit\Domain\Actor;
use YahyaErturan\Audit\Domain\AuditLimits;
use YahyaErturan\Audit\Domain\AuditRecord;
use YahyaErturan\Audit\Domain\Change;
use YahyaErturan\Audit\Domain\Changes;
use YahyaErturan\Audit\Domain\Subject;
use YahyaErturan\Audit\Normalization\NormalizerChain;
use YahyaErturan\Audit\Persistence\Sql\Connection\PdoSqlConnection;
use YahyaErturan\Audit\Persistence\Sql\Schema\SqlAuditSchemaManager;
use YahyaErturan\Audit\Persistence\Sql\SqlAuditReader;
use YahyaErturan\Audit\Persistence\Sql\SqlAuditStore;
use YahyaErturan\Audit\Query\AuditQuery;
use YahyaErturan\Audit\Recording\DefaultAuditor;
use YahyaErturan\Audit\Recording\NullAuditContextProvider;
use YahyaErturan\Audit\Recording\SystemClock;
use YahyaErturan\Audit\Recording\UuidV7AuditIdGenerator;
use YahyaErturan\Audit\Redaction\RedactionPipeline;
// 1. Wrap a PDO connection (create PDO in exception mode).
$pdo = new PDO('sqlite:/var/lib/app/audit.sqlite');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$connection = PdoSqlConnection::fromPdo($pdo);
// 2. Create the schema with the package-owned migrations (idempotent).
(new SqlAuditSchemaManager($connection))->migrate();
// 3. Build the recorder from its explicit, injectable dependencies.
$limits = AuditLimits::defaults();
$auditor = new DefaultAuditor(
store: SqlAuditStore::create($connection),
clock: new SystemClock(),
idGenerator: new UuidV7AuditIdGenerator(),
contextProvider: new NullAuditContextProvider(),
normalizer: NormalizerChain::withDefaults($limits),
redactor: RedactionPipeline::withDefaults(),
limits: $limits,
);
// 4. Record a semantic fact.
$entry = $auditor->record(
AuditRecord::for('invoice.paid')
->by(Actor::identified('user', '42', 'Ada Lovelace'))
->on(Subject::identified('invoice', 'INV-123', 'March invoice'))
->withChanges(Changes::from([
'status' => Change::replaced('open', 'paid'),
]))
->withMetadata(['channel' => 'stripe', 'amount_cents' => 5000])
);
// 5. Read it back.
$reader = SqlAuditReader::create($connection);
$found = $reader->find($entry->id()); // ?AuditEntry
$page = $reader->search(AuditQuery::all()->limit(50));
$pdo = new PDO(
'pgsql:host=localhost;port=5432;dbname=app',
'app_user',
'secret',
[PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION],
);
$connection = PdoSqlConnection::fromPdo($pdo);
(new SqlAuditSchemaManager($connection))->migrate();
AuditRecord::for('customer.email.changed') // semantic, lowercase, dot-separated event name
->by(Actor::identified('user', '42')) // or Actor::system('scheduler'), Actor::anonymous()
->on(Subject::identified('customer', 'C-9')) // optional; omit when there is no resource identity
->withChanges(Changes::from([
'email' => Change::replaced('[email protected]', '[email protected]'),
'phone' => Change::added('+15551234567'),
'fax' => Change::removed('old-fax'),
]))
->withMetadata(['reason' => 'user_request'])
->withTenantId('acme') // optional tenancy dimension
->occurredAt($someDateTime); // optional; defaults to the clock's now()
$page = $reader->search(
AuditQuery::all()
->forTenant('acme')
->forEvent('invoice.paid') // or ->eventPrefix('invoice.')
->byActor('user', '42')
->since(new DateTimeImmutable('2026-01-01'))
->limit(100) // 1..500, default 100
);
foreach ($page->entries() as $entry) {
// $entry is an immutable AuditEntry
}
if ($page->hasMore()) {
$next = $reader->search(AuditQuery::all()->forTenant('acme')->after($page->nextCursor()));
}
$connection->beginTransaction();
$invoiceRepository->markPaid($invoiceId); // your business change
$auditor->record(AuditRecord::for('invoice.paid')->on($subject));
$connection->commit(); // or rollBack() — the audit row follows