Ga naar de inhoud

Filters

Filters bepalen welke gegevens in een snapshot worden opgenomen. Sluit cachetabellen uit, negeer vluchtige tijdstempelkolommen of sla tijdelijke rijen over. Filters worden toegepast tijdens het vastleggen van een snapshot en zijn van invloed op alle daaropvolgende bewerkingen (diff, merge, apply).

PHP
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

Bepaalt welke tabellen in een snapshot worden opgenomen. Ondersteunt globpatronen via PHP's fnmatch().

Tabellen uitsluiten

PHP
use Merql\Filter\TableFilter;

$filter = TableFilter::exclude(['sessions', 'cache_*', 'wp_*_log']);

Tabellen die overeenkomen met een uitsluitingspatroon worden weggelaten uit de snapshot. Het jokerteken * komt overeen met elke tekenreeks.

Tabellen opnemen

PHP
$filter = TableFilter::include(['posts', 'comments', 'users']);

Alleen tabellen die overeenkomen met een opnamepatroon worden vastgelegd. Alle andere worden uitgesloten.

Werking

De apply()-methode van het filter neemt een lijst met tabelnamen aan en retourneert de gefilterde subset:

PHP
$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']

Wanneer zowel opname- als uitsluitingspatronen aanwezig zijn (via afzonderlijke filterinstanties), wordt eerst uitgesloten. Een tabel wordt alleen behouden als deze met geen enkel uitsluitingspatroon overeenkomt en met minstens één opnamepatroon.

ColumnFilter

Verwijdert specifieke kolommen uit rijgegevens tijdens het vastleggen. Handig voor vluchtige kolommen die bij elke schrijfbewerking veranderen en daardoor onjuiste diffs zouden veroorzaken.

PHP
use Merql\Filter\ColumnFilter;

$filter = ColumnFilter::ignore(['updated_at', 'modified_date', 'last_login']);

Veelvoorkomende toepassingen

  • Tijdstempels updated_at / modified_at die bij elke opslag veranderen.
  • revision tellers die automatisch oplopen.
  • session_token of andere tijdelijke velden.

Werking

Het filter verwijdert benoemde kolommen uit elke rij nadat de rijsleutel is berekend:

PHP
$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']

De rijsleutel (identiteit) wordt berekend op basis van de ongefilterde rij. Dit betekent dat identiteitskolommen nooit door het kolomfilter worden beïnvloed. Alleen de gegevens die worden gebruikt voor fingerprinting en het vergelijken van verschillen, worden gefilterd.

RowFilter

Filtert afzonderlijke rijen met een predicaatclosure. De closure ontvangt de tabelnaam en de volledige rijgegevens en retourneert true om de rij op te nemen of false om deze uit te sluiten.

PHP
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;
});

Werking

De shouldInclude()-methode wordt tijdens het vastleggen voor elke rij aangeroepen:

PHP
$include = $filter->shouldInclude('posts', ['id' => 1, 'status' => 'draft']);
// false

Uitgesloten rijen krijgen geen fingerprint, worden niet in de snapshot opgeslagen en verschijnen niet in diffs of merges.

Filters combineren

Geef meerdere filters door aan capture(). Van elk filtertype wordt er hoogstens één gebruikt:

PHP
$snapshot = $snapshotter->capture('baseline', filters: [
    TableFilter::exclude(['cache_*']),
    ColumnFilter::ignore(['updated_at']),
    RowFilter::create(fn($table, $row) => ($row['active'] ?? '1') === '1'),
]);

Verwerkingsvolgorde:

  1. TableFilter wordt als eerste uitgevoerd en bepaalt welke tabellen worden vastgelegd.
  2. Per tabel worden rijen uit de database gelezen.
  3. RowFilter wordt op elke rij uitgevoerd en sluit niet-overeenkomende rijen uit.
  4. De rijsleutel wordt berekend op basis van de ongefilterde rij (identiteitskolommen intact).
  5. ColumnFilter verwijdert genegeerde kolommen uit de rijgegevens.
  6. De fingerprint wordt berekend op basis van de gefilterde rijgegevens.

Dankzij deze volgorde zijn identiteitskolommen altijd beschikbaar voor het berekenen van de sleutel, zelfs als het kolomfilter ze daarna verwijdert.

Filters en consistentie

Gebruik voor alle drie de snapshots in een merge (base, ours, theirs) dezelfde filters. Bij verschillende filters kunnen rijen of kolommen lijken te zijn toegevoegd of verwijderd, terwijl ze alleen anders zijn gefilterd.

PHP
// 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);