This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
auditor is a provider-agnostic PHP library (namespace DH\Auditor) that provides the core infrastructure for audit logging. It defines the contracts (ProviderInterface, AuditingServiceInterface, StorageServiceInterface) and core models (Entry, TransactionType, LifecycleEvent) that concrete provider packages implement. Active development targets 5.x (PHP ≥ 8.4, Symfony ≥ 8.0).
The Doctrine ORM provider lives in the separate damienharper/auditor-doctrine-provider package.
composer test # all tests, no coverage
composer test:coverage # with Xdebug coverage
composer testdox # testdox format
vendor/bin/phpunit --filter=AuditorTest # single test classcomposer cs-fix # fix style (php-cs-fixer)
composer cs-check # dry-run style check
composer phpstan # static analysis (level max)
composer qa # rector + cs-fix + phpstanWhen running as an AI agent, use these variants instead — they suppress progress bars and verbose output while still surfacing errors:
composer agent-cs-fix # php-cs-fixer --quiet
composer agent-phpstan # phpstan --no-progress
composer agent-rector # rector --no-progress-bar
composer agent-test # phpunit --no-progress
composer agent-qa # agent-rector + agent-cs-fix + agent-phpstancomposer update-tools # updates php-cs-fixer, phpstan, rector independentlyThe library provides the event bus and contracts; providers implement the actual auditing and storage logic.
Auditor (src/Auditor.php)
└─ registers ProviderInterface implementations
└─ (e.g. DoctrineProvider from auditor-doctrine-provider)
Auditor wires a single AuditEventSubscriber (priority -1,000,000) onto Symfony's EventDispatcherInterface to catch LifecycleEvent and fan it out to registered providers.
| Class | Path | Purpose |
|---|---|---|
Auditor |
src/Auditor.php |
Main entry point; manages providers |
ProviderInterface |
src/Provider/ProviderInterface.php |
Contract all providers must implement |
AbstractProvider |
src/Provider/AbstractProvider.php |
Base provider implementation |
Entry |
src/Model/Entry.php |
Hydrated audit log row (read model) |
TransactionType |
src/Model/TransactionType.php |
Backed string enum for operation types |
LifecycleEvent |
src/Event/LifecycleEvent.php |
Event dispatched per audit entry |
AuditEventSubscriber |
src/EventSubscriber/AuditEventSubscriber.php |
Fans LifecycleEvent out to providers |
Three attributes live in src/Attribute/:
#[Auditable]— marks an entity class as auditable#[Ignore]— marks a field to skip#[Security]— restricts who can view audit entries for an entity
src/Provider/Service/ defines abstract service interfaces:
AuditingServiceInterface— detects changes and producesLifecycleEventsStorageServiceInterface— persists audit entries
- Tests mirror
src/structure undertests/ - Core tests cover
Auditor,Configuration,LifecycleEvent,Entry,TransactionType, and the event subscriber
$entry->typeis a plainstring('insert','update', etc.)$entry->extraDatais a virtual property that returns?array(alreadyjson_decode'd) — do not calljson_decode()on it$entry->objectId,$entry->transactionHash,$entry->userId,$entry->usernameetc. are virtual properties backed by snake_case private fields
entity (FQCN), table, type (string operation), object_id, discriminator, transaction_hash, diffs, extra_data, blame_id, blame_user, blame_user_fqdn, blame_user_firewall, ip, created_at. No action key at the LifecycleEvent level — use $payload['type'].
- php-cs-fixer, phpstan, and rector each have their own isolated Composer project under
tools/. Never run them directly viavendor/bin/— use thetools/paths or thecomposerscripts. - PHPStan runs at level max; new code must type-hint everything. Current suppressions for PHPStan 2.x stricter checks are tracked in
phpstan.neon. - The
rector.phpconfig controls automated refactoring rules.