Filter
Filter steuern, welche Daten in einen Snapshot aufgenommen werden. Schließe Cache-Tabellen aus, ignoriere veränderliche Zeitstempelspalten oder überspringe temporäre Zeilen. Die Filter werden während der Snapshot-Erfassung angewendet und wirken sich auf alle nachgelagerten Vorgänge aus (Diff, Merge, Apply).
use Merql\Filter\TableFilter;
use Merql\Filter\ColumnFilter;
use Merql\Snapshot\Snapshotter;
$snapshotter = new Snapshotter($connection);
$snapshot = $snapshotter->capture('baseline', filters: [
TableFilter::exclude(['sessions', 'cache_*']),
ColumnFilter::ignore(['updated_at', 'modified_date']),
]);
TableFilter
Legt fest, welche Tabellen in einen Snapshot aufgenommen werden. Unterstützt Glob-Muster über PHPs fnmatch().
Tabellen ausschließen
use Merql\Filter\TableFilter;
$filter = TableFilter::exclude(['sessions', 'cache_*', 'wp_*_log']);
Tabellen, die einem Ausschlussmuster entsprechen, werden aus dem Snapshot ausgelassen. Der Platzhalter * steht für eine beliebige Zeichenfolge.
Tabellen einschließen
$filter = TableFilter::include(['posts', 'comments', 'users']);
Nur Tabellen, die einem Einschlussmuster entsprechen, werden erfasst. Alle anderen werden ausgeschlossen.
Funktionsweise
Die Methode apply() des Filters nimmt eine Liste von Tabellennamen entgegen und gibt die gefilterte Teilmenge zurück:
$allTables = ['posts', 'comments', 'sessions', 'cache_pages', 'users'];
$filter = TableFilter::exclude(['sessions', 'cache_*']);
$filtered = $filter->apply($allTables);
// ['posts', 'comments', 'users']
$filter = TableFilter::include(['posts', 'users']);
$filtered = $filter->apply($allTables);
// ['posts', 'users']
Wenn Einschluss- und Ausschlussmuster vorhanden sind (über separate Filterinstanzen), wird der Ausschluss zuerst ausgewertet. Eine Tabelle bleibt erhalten, wenn sie keinem Ausschlussmuster und mindestens einem Einschlussmuster entspricht.
ColumnFilter
Entfernt bei der Erfassung bestimmte Spalten aus den Zeilendaten. Nützlich für veränderliche Spalten, die sich bei jedem Schreibvorgang ändern und falsche Diffs verursachen würden.
use Merql\Filter\ColumnFilter;
$filter = ColumnFilter::ignore(['updated_at', 'modified_date', 'last_login']);
Häufige Anwendungsfälle
updated_at/modified_at-Zeitstempel, die sich bei jedem Speichern ändern.revision-Zähler, die automatisch hochgezählt werden.session_tokenoder andere temporäre Felder.
Funktionsweise
Der Filter entfernt benannte Spalten aus jeder Zeile, nachdem der Zeilenschlüssel berechnet wurde:
$filter = ColumnFilter::ignore(['updated_at']);
$row = ['id' => 1, 'title' => 'Hello', 'updated_at' => '2026-01-15 10:30:00'];
$filtered = $filter->applyToRow($row);
// ['id' => 1, 'title' => 'Hello']
Der Zeilenschlüssel (Identität) wird anhand der ungefilterten Zeile berechnet. Daher sind Identitätsspalten vom Spaltenfilter nicht betroffen. Gefiltert werden nur die Daten, die für Fingerprinting und Diff-Berechnungen verwendet werden.
RowFilter
Filtert einzelne Zeilen mithilfe einer Prädikat-Closure. Die Closure erhält den Tabellennamen und die vollständigen Zeilendaten und gibt true zurück, um die Zeile einzuschließen, oder false, um sie auszuschließen.
use Merql\Filter\RowFilter;
// Exclude draft posts.
$filter = RowFilter::create(function (string $table, array $row): bool {
if ($table === 'posts' && ($row['status'] ?? '') === 'draft') {
return false;
}
return true;
});
// Exclude rows with NULL email.
$filter = RowFilter::create(function (string $table, array $row): bool {
if ($table === 'users') {
return $row['email'] !== null;
}
return true;
});
Funktionsweise
Die Methode shouldInclude() wird während der Erfassung für jede Zeile aufgerufen:
$include = $filter->shouldInclude('posts', ['id' => 1, 'status' => 'draft']);
// false
Ausgeschlossene Zeilen werden nicht mit einem Fingerprint versehen, nicht im Snapshot gespeichert und erscheinen weder in Diffs noch in Merges.
Filter kombinieren
Übergib mehrere Filter an capture(). Es wird höchstens ein Filter jedes Typs verwendet:
$snapshot = $snapshotter->capture('baseline', filters: [
TableFilter::exclude(['cache_*']),
ColumnFilter::ignore(['updated_at']),
RowFilter::create(fn($table, $row) => ($row['active'] ?? '1') === '1'),
]);
Verarbeitungsreihenfolge:
- TableFilter wird zuerst ausgeführt und bestimmt, welche Tabellen erfasst werden.
- Für jede Tabelle werden die Zeilen aus der Datenbank gelesen.
- RowFilter wird auf jede Zeile angewendet und schließt nicht passende Zeilen aus.
- Der Zeilenschlüssel wird anhand der ungefilterten Zeile berechnet (Identitätsspalten bleiben erhalten).
- ColumnFilter entfernt ignorierte Spalten aus den Zeilendaten.
- Der Fingerprint wird anhand der gefilterten Zeilendaten berechnet.
Diese Reihenfolge stellt sicher, dass Identitätsspalten für die Berechnung des Schlüssels verfügbar bleiben, auch wenn der Spaltenfilter sie später entfernt.
Filter und Konsistenz
Für alle drei Snapshots eines Merge-Vorgangs (Basis, ours, theirs) sollten dieselben Filter verwendet werden. Bei unterschiedlichen Filtern können Zeilen oder Spalten als hinzugefügt oder entfernt erscheinen, obwohl sie lediglich unterschiedlich gefiltert wurden.
// Use the same filter set for all snapshots.
$filters = [
TableFilter::exclude(['sessions']),
ColumnFilter::ignore(['updated_at']),
];
$base = $snapshotter->capture('base', filters: $filters);
$ours = $snapshotter->capture('ours', filters: $filters);
$theirs = $snapshotter->capture('theirs', filters: $filters);