PHP code example of metadev / doctrine-audit-trail-bundle
1. Go to this page and download the library: Download metadev/doctrine-audit-trail-bundle 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/ */
metadev / doctrine-audit-trail-bundle example snippets
use Metadev\DoctrineAuditTrailBundle\Attribute\Auditable;
use Metadev\DoctrineAuditTrailBundle\Attribute\AuditIgnore;
#[Auditable(label: 'Blog post')]
class Post
{
#[AuditIgnore] // never recorded in the diff
private ?string $internalToken = null;
// ...
}
#[Auditable]
class Order
{
#[ORM\Embedded(class: Money::class)]
public Money $price; // recorded as price.amount / price.currency
#[ORM\Embedded(class: Credentials::class)]
#[AuditIgnore]
public Credentials $providerCreds; // every sub-field hidden
#[ORM\Embedded(class: Credentials::class, columnPrefix: 'exposed_')]
public Credentials $exposedCreds; // .login is recorded; .secret / .apiKey are
// still filtered by the default deny-list
}
use Metadev\DoctrineAuditTrailBundle\Repository\AuditTrailEntryRepository;
public function history(AuditTrailEntryRepository $repository): void
{
$entries = $repository->findByEntity(Post::class, $postId);
$byUser = $repository->findByActor('jane_admin');
}
use Metadev\DoctrineAuditTrailBundle\Diff\Formatter\ValueFormatterInterface;
// Auto-tagged via the interface; priority 0 runs before the built-ins (-500 / -1000).
final class MoneyFormatter implements ValueFormatterInterface
{
public function supports(mixed $value): bool { return $value instanceof Money; }
public function format(mixed $value): mixed { return $value->getAmount(); }
}
final class CategoryLabelFormatter implements ValueFormatterInterface
{
public function supports(mixed $value): bool
{
return $value instanceof Category;
}
public function format(mixed $value): array
{
return [
'class' => $value::class,
'id' => $value->getId(),
'label' => $value->getName(), // must not trigger DB I/O
];
}
}
use Metadev\DoctrineAuditTrailBundle\User\AuditActor;
use Metadev\DoctrineAuditTrailBundle\User\AuditUserResolverInterface;
use Symfony\Component\DependencyInjection\Attribute\AsDecorator;
use Symfony\Component\DependencyInjection\Attribute\Autowire;
use Symfony\Component\DependencyInjection\Attribute\AutowireDecorated;
#[AsDecorator(decorates: AuditUserResolverInterface::class)]
final readonly class GdprAuditUserResolver implements AuditUserResolverInterface
{
public function __construct(
#[AutowireDecorated] private AuditUserResolverInterface $inner,
#[Autowire('%kernel.secret%')] private string $salt,
) {
}
public function resolve(): AuditActor
{
$actor = $this->inner->resolve();
return $actor
// CNIL: drop the last octet — 192.168.1.42 → 192.168.1.0
->withIpAddress(
null === $actor->ipAddress
? null
: preg_replace('/\.\d+$/', '.0', $actor->ipAddress),
)
// Pseudonymise the identifier with a salted hash
->withUserIdentifier(
null === $actor->userIdentifier
? null
: hash('sha256', $actor->userIdentifier.$this->salt),
);
}
}
$this->contextHolder->setActor(new AuditActor(label: 'batch-nightly'));
// ... run the batch ...
$this->contextHolder->reset();
bash
# Recommended — generate a migration in your project's namespace:
php bin/console make:migration --em=audit
php bin/console doctrine:migrations:migrate --em=audit
# Quick start for demos / dev:
php bin/console doctrine:schema:update --em=audit --force
Loading please wait ...
Before you can download the PHP files, the dependencies should be resolved. This can take some minutes. Please be patient.