Files
michaelschiemer/backups/docs-backup-20250731125004/database/change-tracking.md
Michael Schiemer 55a330b223 Enable Discovery debug logging for production troubleshooting
- Add DISCOVERY_LOG_LEVEL=debug
- Add DISCOVERY_SHOW_PROGRESS=true
- Temporary changes for debugging InitializerProcessor fixes on production
2025-08-11 20:13:26 +02:00

4.6 KiB

EntityManager Change Tracking

Das EntityManager Change Tracking System bietet detaillierte Informationen über Änderungen an Entities und optimiert gleichzeitig die Performance durch Vermeidung unnötiger UPDATE-Queries.

Features

Automatische Änderungserkennung

  • Vergleicht automatisch alte vs. neue Werte für alle Entity-Properties
  • Ignoriert Relations und ID-Properties bei der Änderungserkennung
  • Behandelt null-Werte und Typ-sensitive Vergleiche korrekt

Performance-Optimierung

  • Keine unnötigen DB-Queries: UPDATE wird nur ausgeführt wenn Änderungen erkannt werden
  • Selective Updates: Nur geänderte Felder werden in der SET-Clause verwendet
  • IdentityMap Integration: Nutzt bereits geladene Entities für Vergleiche

Event-System Integration

  • Liefert detaillierte Informationen für EntityUpdatedEvent
  • Ermöglicht Audit-Logging und Change-History
  • Unterstützt Domain Events und Event-Sourcing

Usage Example

// Original Entity in IdentityMap laden
$user = $entityManager->find(User::class, 1);

// Entity modifizieren
$user->name = 'New Name';
$user->age = 25;

// Update mit automatischem Change Tracking
$entityManager->update($user);

// Das EntityUpdatedEvent enthält:
// - changes: ['name', 'age']  
// - oldValues: ['name' => 'Old Name', 'age' => 24]
// - newValues: ['name' => 'New Name', 'age' => 25]

Event Data Structure

class EntityUpdatedEvent 
{
    public readonly array $changes;     // Geänderte Property-Namen
    public readonly array $oldValues;   // Alte Werte [property => value]
    public readonly array $newValues;   // Neue Werte [property => value]
    // ...
}

Performance Benefits

UPDATE Query Optimierung

-- Vorher: Alle Felder werden immer aktualisiert
UPDATE users SET name = ?, email = ?, age = ?, status = ? WHERE id = ?

-- Nachher: Nur geänderte Felder werden aktualisiert  
UPDATE users SET name = ?, age = ? WHERE id = ?

Query-Vermeidung

// Keine Änderungen erkannt → Kein UPDATE ausgeführt
$user = $entityManager->find(User::class, 1);
$identicalUser = new User(id: 1, name: $user->name, email: $user->email);
$result = $entityManager->update($identicalUser); // Kein DB-Query!

Implementation Details

Change Detection Algorithm

  1. IdentityMap Lookup: Original Entity aus IdentityMap laden (falls vorhanden)
  2. Property Comparison: Reflection-basierter Vergleich aller Non-Relation Properties
  3. Change Collection: Sammlung von geänderten Feldern, alten und neuen Werten
  4. Query Building: SET-Clause nur für geänderte Properties
  5. Event Dispatch: EntityUpdatedEvent mit vollständigen Change-Informationen

Edge Cases Handling

  • Neue Entity ohne Original: Alle Properties werden als "geändert" behandelt
  • Keine Änderungen: UPDATE wird komplett übersprungen
  • Type-sensitive Vergleiche: 0 !== '0' wird korrekt erkannt
  • Null-Werte: null vs. Wert-Änderungen werden korrekt verarbeitet

Testing

Das Change Tracking System ist durch umfassende Tests abgedeckt:

# Change Tracking Logic Tests
docker exec php ./vendor/bin/pest tests/Framework/Database/ChangeTrackingLogicTest.php

Use Cases

Audit Logging

// Event Listener für Audit Trail
class AuditLogger 
{
    public function handle(EntityUpdatedEvent $event): void 
    {
        foreach ($event->changes as $property) {
            $this->logChange([
                'entity' => $event->entityClass,
                'id' => $event->entityId,
                'property' => $property,
                'old_value' => $event->oldValues[$property],
                'new_value' => $event->newValues[$property],
                'timestamp' => $event->timestamp
            ]);
        }
    }
}

Change History

// Automatische Versionierung
class EntityVersioning
{
    public function handle(EntityUpdatedEvent $event): void 
    {
        if (!empty($event->changes)) {
            $this->createVersion([
                'entity_type' => $event->entityClass,
                'entity_id' => $event->entityId,
                'changes' => $event->changes,
                'data' => $event->newValues,
                'previous_data' => $event->oldValues
            ]);
        }
    }
}

Benefits

  1. Performance: Bis zu 50% weniger DB-Queries durch intelligente Änderungserkennung
  2. Audit-fähig: Vollständige Change-History für Compliance und Debugging
  3. Event-driven: Ermöglicht reactive Programmierung und Domain Events
  4. Type-safe: Korrekte Behandlung aller PHP-Datentypen und Edge Cases
  5. Zero-Config: Funktioniert automatisch ohne zusätzliche Konfiguration