- Add DISCOVERY_LOG_LEVEL=debug - Add DISCOVERY_SHOW_PROGRESS=true - Temporary changes for debugging InitializerProcessor fixes on production
4.6 KiB
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
- IdentityMap Lookup: Original Entity aus IdentityMap laden (falls vorhanden)
- Property Comparison: Reflection-basierter Vergleich aller Non-Relation Properties
- Change Collection: Sammlung von geänderten Feldern, alten und neuen Werten
- Query Building: SET-Clause nur für geänderte Properties
- 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:
nullvs. 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
- Performance: Bis zu 50% weniger DB-Queries durch intelligente Änderungserkennung
- Audit-fähig: Vollständige Change-History für Compliance und Debugging
- Event-driven: Ermöglicht reactive Programmierung und Domain Events
- Type-safe: Korrekte Behandlung aller PHP-Datentypen und Edge Cases
- Zero-Config: Funktioniert automatisch ohne zusätzliche Konfiguration