Skip to main content
Version: 7.x

Storage Configuration

Configure audit storage, including multi-database setups

This guide covers audit storage configuration, including multi-database setups.

πŸ—„οΈ Default Setup​

By default, audits are stored in the same database as your entities using the default entity manager:

dh_auditor:
providers:
doctrine:
storage_services:
- '@doctrine.orm.default_entity_manager'

This provides transactional integrity: audit entries are part of the same database transaction as entity changes.

πŸ“ Table Naming​

Audit tables are named: {prefix}{entity_table}{suffix}

OptionDefaultExample (entity: users)
table_prefix''β†’ users_audit
table_suffix'_audit'β†’ users_audit
dh_auditor:
providers:
doctrine:
table_prefix: 'audit_'
table_suffix: ''

Result: users β†’ audit_users

πŸ—ƒοΈ Multi-Database Setup​

Store audits in a separate database from your entities.

CAUTION

Warning: Atomicity

Using separate databases breaks transactional integrity:

  • Entity changes and audits are in different transactions
  • If entity operation succeeds but audit fails β†’ missing audit
  • If entity operation fails but audit succeeds β†’ orphan audit

Only use this when the trade-offs are acceptable.

Configuration​

1️⃣ Configure Multiple Entity Managers​

# config/packages/doctrine.yaml
doctrine:
dbal:
default_connection: default
connections:
default:
url: '%env(DATABASE_URL)%'
audit:
url: '%env(AUDIT_DATABASE_URL)%'

orm:
default_entity_manager: default
entity_managers:
default:
connection: default
mappings:
App:
type: attribute
dir: '%kernel.project_dir%/src/Entity'
prefix: 'App\Entity'
audit:
connection: audit
# No mappings needed - audit tables are created dynamically

2️⃣ Configure Storage Services​

# config/packages/dh_auditor.yaml
dh_auditor:
providers:
doctrine:
storage_services:
- '@doctrine.orm.audit_entity_manager'

auditing_services:
- '@doctrine.orm.default_entity_manager'

entities:
App\Entity\User: ~

πŸ—ΊοΈ Storage Mapper​

When using multiple storage services, a storage mapper routes audits to the correct database.

Creating a Storage Mapper​

<?php

namespace App\Audit;

use DH\Auditor\Provider\Service\StorageServiceInterface;

class StorageMapper
{
/**
* @param string $entity The audited entity FQCN
* @param array<string, StorageServiceInterface> $storageServices
*/
public function __invoke(string $entity, array $storageServices): StorageServiceInterface
{
// All audits go to the audit database
return $storageServices['dh_auditor.provider.doctrine.storage_services.doctrine.orm.audit_entity_manager'];
}
}

Routing by Entity​

<?php

namespace App\Audit;

use App\Entity\HighSecurityEntity;
use App\Entity\SensitiveData;
use DH\Auditor\Provider\Service\StorageServiceInterface;

class StorageMapper
{
private const SECURE_ENTITIES = [
HighSecurityEntity::class,
SensitiveData::class,
];

public function __invoke(string $entity, array $storageServices): StorageServiceInterface
{
if (in_array($entity, self::SECURE_ENTITIES, true)) {
return $storageServices['dh_auditor.provider.doctrine.storage_services.doctrine.orm.secure_entity_manager'];
}

return $storageServices['dh_auditor.provider.doctrine.storage_services.doctrine.orm.default_entity_manager'];
}
}

Configuration​

# config/packages/dh_auditor.yaml
dh_auditor:
providers:
doctrine:
storage_services:
- '@doctrine.orm.default_entity_manager'
- '@doctrine.orm.secure_entity_manager'

storage_mapper: 'App\Audit\StorageMapper'

πŸ”§ Schema Management​

Single Database​

Use standard Doctrine tools:

# With migrations (recommended)
bin/console doctrine:migrations:diff
bin/console doctrine:migrations:migrate

# Or schema tool
bin/console doctrine:schema:update --force

Multiple Databases​

Use the audit schema command:

# Preview changes
bin/console audit:schema:update --dump-sql

# Apply changes
bin/console audit:schema:update --force

This command handles all configured storage services.

πŸ—οΈ Architecture Comparison​

βœ… Same transaction = Data integrity

Separate Database​

⚠️ Different transactions = Possible inconsistency


πŸš€ Next Steps​