Doctrine Changelog Component
softspring/doctrine-changelog-bundle is a technical component for Symfony applications that need an audit trail or a change stream based on Doctrine entity lifecycle changes.
It listens to Doctrine onFlush, creates change entries for tracked entities, enriches them with context, and then either stores them with a driver or leaves them available for your own listeners.
What It Provides
- change detection for entity insertions, updates, and deletions
- registrable and ignored markers for entity classes and fields
- change events that application code can subscribe to
- optional collectors for request, user, and action metadata
- an in-memory
ChangesStack - storage drivers for Doctrine and BigQuery
This package is infrastructure, not UI. It does not ship routes, screens, or backoffice pages.
Install
composer require softspring/doctrine-changelog-bundle:^6.0
If your application does not use Symfony Flex, enable the bundle manually:
<?php
return [
// ...
Softspring\DoctrineChangeLogBundle\SfsDoctrineChangeLogBundle::class => ['all' => true],
];
Basic Configuration
# config/packages/sfs_doctrine_change_log.yaml
sfs_doctrine_change_log:
collect:
request: true
user: true
action: true
storage:
enabled: false
That setup already gives you change events and an in-memory stack. It does not persist anything yet.
Which Entities Are Tracked
Only entities marked as registrable are tracked.
In this line you can use either annotations or PHP attributes:
<?php
namespace App\Entity;
use Softspring\DoctrineChangeLogBundle\Mapping as ChangeLog;
#[ChangeLog\Registrable([])]
class Product
{
#[ChangeLog\Ignored([])]
private string $updatedByCache;
}
Ignored fields are removed from the Doctrine change set before the changelog event is dispatched.
Runtime Flow
At runtime, the component works in four steps:
DoctrineChangesListenerreads scheduled entity insertions, updates, and deletions inonFlush- it builds one
ChangeEntryper tracked entity change - collector listeners enrich that entry with metadata
- if storage is enabled,
ChangesPersistListenerpersists the stacked entries onkernel.terminate
This means you can use the component in two ways:
- as a complete changelog persistence layer
- as an internal event source that your own application code consumes
Collected Metadata
The optional collectors add:
- request data
- IP, user agent, method, path
- user data
- current authenticated user identifier
- action
insertion,update, ordeletion
These are controlled by the collect block and are independent from the actual Doctrine change detection.
Storage Modes
Disabled Storage
When storage.enabled is false, the component still dispatches change events and fills the stack, but it does not persist them.
This is useful when your application wants to forward changes to its own queue, stream, or audit service.
Doctrine Storage
sfs_doctrine_change_log:
storage:
enabled: true
driver: doctrine
The Doctrine driver expects your application to provide a concrete changelog entity, typically extending Softspring\DoctrineChangeLogBundle\Entity\ChangeLog.
This is a good fit when:
- you want a local audit table
- audit queries stay in the same relational database
- operational simplicity matters more than warehouse-style analytics
BigQuery Storage
sfs_doctrine_change_log:
storage:
enabled: true
driver: big-query
big_query:
project: '%env(BIGQUERY_PROJECT)%'
dataset: '%env(BIGQUERY_DATASET)%'
table:
mode: fixed
fixed:
name: changelog
BigQuery is the better fit when:
- changes should be exported to a warehouse
- analytics and reporting matter more than local ORM access
- the audit stream belongs to a broader data platform
Practical Integration Advice
- use registrable markers only on entities whose changes have business value
- ignore noisy cache or denormalized fields
- start with storage disabled if you first want to validate the event stream
- use Doctrine storage for audit tables and BigQuery for analytics pipelines
- keep collection changes explicit through relation entities, because this component tracks entity changes, not generic collection diffs
Extension Points
The main extension points are:
- custom listeners for
InsertionChangeEvent,UpdateChangeEvent, andDeletionChangeEvent - custom storage drivers implementing
StorageDriverInterface - custom collector listeners that enrich
ChangeEntry - custom changelog entity classes when using Doctrine storage
This is where the component adds value: it standardizes the change capture layer and leaves persistence and downstream usage open.