Filtre
Filtrele controlează ce date sunt incluse într-un instantaneu. Excludeți tabelele de cache, ignorați coloanele cu marcaje temporale volatile sau omiteți rândurile tranzitorii. Filtrele se aplică în timpul capturării instantaneului și afectează toate operațiunile ulterioare (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
Controlează ce tabele sunt incluse într-un instantaneu. Acceptă modele glob prin PHP fnmatch().
Excluderea tabelelor
use Merql\Filter\TableFilter;
$filter = TableFilter::exclude(['sessions', 'cache_*', 'wp_*_log']);
Orice tabel care corespunde unui model de excludere este omis din instantaneu. Caracterul wildcard * corespunde oricărei secvențe de caractere.
Includerea tabelelor
$filter = TableFilter::include(['posts', 'comments', 'users']);
Sunt capturate numai tabelele care corespund unui model de includere. Toate celelalte sunt excluse.
Cum funcționează
Metoda apply() a filtrului primește o listă de nume de tabele și returnează subsetul filtrat:
$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']
Când sunt prezente atât modele de includere, cât și de excludere (prin instanțe de filtre separate), excluderea este evaluată prima. Pentru a fi păstrat, un tabel nu trebuie să corespundă niciunui model de excludere și trebuie să corespundă cel puțin unui model de includere.
ColumnFilter
Elimină anumite coloane din datele rândurilor în timpul capturării. Este util pentru coloanele volatile care se modifică la fiecare scriere și ar cauza diferențe false.
use Merql\Filter\ColumnFilter;
$filter = ColumnFilter::ignore(['updated_at', 'modified_date', 'last_login']);
Cazuri de utilizare frecvente
- Marcaje temporale
updated_at/modified_atcare se modifică la fiecare salvare. - Contoare
revisioncare se incrementează automat. session_tokensau alte câmpuri tranzitorii.
Cum funcționează
Filtrul elimină coloanele numite din fiecare rând după calcularea cheii rândului:
$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']
Cheia rândului (identitatea) este calculată din rândul nefiltrat. Asta înseamnă că filtrul de coloane nu afectează niciodată coloanele de identitate. Sunt filtrate doar datele folosite pentru calcularea amprentei și compararea diferențelor.
RowFilter
Filtrează rânduri individuale folosind o funcție predicate de tip closure. Closure-ul primește numele tabelului și datele complete ale rândului și returnează true pentru a include rândul sau false pentru a-l exclude.
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;
});
Cum funcționează
Metoda shouldInclude() este apelată pentru fiecare rând în timpul capturării:
$include = $filter->shouldInclude('posts', ['id' => 1, 'status' => 'draft']);
// false
Rândurile excluse nu primesc amprentă, nu sunt stocate în instantaneu și nu apar în diferențe sau îmbinări.
Combinarea filtrelor
Transmiteți mai multe filtre către capture(). Se folosește cel mult un filtru din fiecare tip:
$snapshot = $snapshotter->capture('baseline', filters: [
TableFilter::exclude(['cache_*']),
ColumnFilter::ignore(['updated_at']),
RowFilter::create(fn($table, $row) => ($row['active'] ?? '1') === '1'),
]);
Ordinea procesării:
- TableFilter rulează prima și stabilește ce tabele să fie capturate.
- Pentru fiecare tabel, rândurile sunt citite din baza de date.
- RowFilter rulează pentru fiecare rând și exclude rândurile care nu corespund.
- Cheia rândului este calculată din rândul nefiltrat (cu coloanele de identitate intacte).
- ColumnFilter elimină coloanele ignorate din datele rândului.
- Amprenta este calculată din datele filtrate ale rândului.
Această ordine asigură că coloanele de identitate sunt întotdeauna disponibile pentru calcularea cheii, chiar dacă filtrul de coloane le elimină ulterior.
Filtre și consecvență
Folosiți aceleași filtre pentru toate cele trei instantanee dintr-o îmbinare (base, ours, theirs). Dacă se folosesc filtre diferite, poate părea că au fost adăugate sau eliminate rânduri ori coloane, deși acestea au fost doar filtrate în mod diferit.
// 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);