Skip to main content
Version: 1.x

Attributes Reference

Configure entity auditing with PHP 8 attributes

Auditor uses PHP 8 attributes to configure Doctrine entity auditing. These attributes are defined in the damienharper/auditor core library and are shared across all providers.

📋 Overview

AttributeTargetDescription
#[Auditable]ClassMarks an entity for auditing
#[Ignore]PropertyExcludes a property from auditing
#[Security]ClassDefines who can view entity audits

📝 #[Auditable]

Marks a Doctrine entity as auditable.

Namespace

use DH\Auditor\Attribute\Auditable;

Usage

<?php

use DH\Auditor\Attribute\Auditable;
use Doctrine\ORM\Mapping as ORM;

#[ORM\Entity]
#[Auditable]
class Post
{
// Entity will be audited
}

Parameters

ParameterTypeDefaultDescription
enabledbooltrueWhether auditing is enabled

Examples

// Auditing enabled (default)
#[Auditable]
class Post {}

// Explicitly enabled
#[Auditable(enabled: true)]
class Post {}

// Disabled by default (can be enabled at runtime)
#[Auditable(enabled: false)]
class DraftPost {}

Enabling/Disabling at Runtime

$configuration = $provider->getConfiguration();

$configuration->disableAuditFor(Post::class);
$configuration->enableAuditFor(Post::class);

🚫 #[Ignore]

Excludes a property from being tracked in audits.

Namespace

use DH\Auditor\Attribute\Ignore;

Usage

<?php

use DH\Auditor\Attribute\Auditable;
use DH\Auditor\Attribute\Ignore;
use Doctrine\ORM\Mapping as ORM;

#[ORM\Entity]
#[Auditable]
class User
{
#[ORM\Column(type: 'string')]
private string $email = '';

#[ORM\Column(type: 'string')]
#[Ignore] // Password changes won't be logged
private string $password = '';

#[ORM\Column(type: 'string', nullable: true)]
#[Ignore] // Tokens shouldn't be in audit logs
private ?string $resetToken = null;
}

Parameters

The #[Ignore] attribute has no parameters.

Common Use Cases

#[ORM\Entity]
#[Auditable]
class User
{
// Security-sensitive fields
#[Ignore]
private string $password = '';

#[Ignore]
private ?string $salt = null;

// Frequently changing but low-value fields
#[Ignore]
private int $loginCount = 0;

#[Ignore]
private ?\DateTimeInterface $lastActivityAt = null;
}

🔐 #[Security]

Defines which roles are allowed to view audits for an entity.

Namespace

use DH\Auditor\Attribute\Security;

Usage

<?php

use DH\Auditor\Attribute\Auditable;
use DH\Auditor\Attribute\Security;
use Doctrine\ORM\Mapping as ORM;

#[ORM\Entity]
#[Auditable]
#[Security(view: ['ROLE_ADMIN'])]
class User
{
// Only users with ROLE_ADMIN can view User audits
}

Parameters

ParameterTypeRequiredDescription
viewarray<string>YesArray of roles allowed to view audits

Examples

// Single role
#[Security(view: ['ROLE_ADMIN'])]
class User {}

// Multiple roles (any of them grants access)
#[Security(view: ['ROLE_ADMIN', 'ROLE_AUDITOR', 'ROLE_COMPLIANCE'])]
class Order {}

How It Works

The role checker callback is invoked when the Reader creates a query:

  1. Reader::createQuery() is called for an entity
  2. The role checker receives the entity class and 'view' scope
  3. If the role checker returns false, an AccessDeniedException is thrown
$configuration->setRoleChecker(function (string $entity, string $scope) use ($provider): bool {
$entities = $provider->getConfiguration()->getEntities();

if (!isset($entities[$entity]['roles'][$scope])) {
return true;
}

foreach ($entities[$entity]['roles'][$scope] as $role) {
if ($this->currentUserHasRole($role)) {
return true;
}
}

return false;
});

📄 Complete Example

<?php

namespace App\Entity;

use DH\Auditor\Attribute\Auditable;
use DH\Auditor\Attribute\Ignore;
use DH\Auditor\Attribute\Security;
use Doctrine\ORM\Mapping as ORM;

#[ORM\Entity]
#[ORM\Table(name: 'users')]
#[Auditable]
#[Security(view: ['ROLE_ADMIN', 'ROLE_USER_AUDITOR'])]
class User
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column(type: 'integer')]
private ?int $id = null;

#[ORM\Column(type: 'string', length: 180, unique: true)]
private string $email = '';

#[ORM\Column(type: 'string')]
#[Ignore] // Don't audit password changes (security)
private string $password = '';

#[ORM\Column(type: 'string', nullable: true)]
#[Ignore] // Don't audit reset tokens
private ?string $resetToken = null;

#[ORM\Column(type: 'integer')]
#[Ignore] // Frequent updates, low audit value
private int $loginCount = 0;
}

🔀 Combining with Programmatic Configuration

TIP

Attributes can be combined with or overridden by programmatic configuration.

use DH\Auditor\Provider\Doctrine\Configuration;

$configuration = new Configuration([
'entities' => [
// Override the Security attribute — more restrictive
User::class => [
'roles' => ['view' => ['ROLE_SUPER_ADMIN']],
],

// Add additional ignored columns on top of attribute-defined ones
Post::class => [
'ignored_columns' => ['view_count'],
],

// Completely disable auditing despite #[Auditable]
DraftPost::class => [
'enabled' => false,
],
],
]);

✅ Best Practices

  1. Always ignore sensitive data — Passwords, tokens, secrets, salts
  2. Use #[Security] for sensitive entities — Users, payments, orders, etc.
  3. Consider ignoring high-frequency low-value columnslast_activity_at, counters
  4. Apply the principle of least privilege — Start restrictive, relax as needed

WARNING

Never audit password fields or authentication tokens. Always use #[Ignore] on all security-sensitive properties.


Next Steps