Vai al contenuto

Filtri

I filtri controllano quali dati vengono inclusi in uno snapshot. Escludete le tabelle della cache, ignorate le colonne con timestamp variabili o saltate le righe temporanee. I filtri vengono applicati durante l’acquisizione dello snapshot e influiscono su tutte le operazioni successive (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

Controlla quali tabelle sono incluse in uno snapshot. Supporta i modelli glob tramite il fnmatch() di PHP.

Escludere tabelle

PHP
use Merql\Filter\TableFilter;

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

Le tabelle che corrispondono a un modello di esclusione vengono omesse dallo snapshot. Il carattere jolly * corrisponde a qualsiasi sequenza di caratteri.

Includere tabelle

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

Vengono acquisite solo le tabelle che corrispondono a un modello di inclusione. Tutte le altre vengono escluse.

Come funziona

Il metodo apply() del filtro riceve un elenco di nomi di tabelle e restituisce il sottoinsieme filtrato:

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

Quando sono presenti sia modelli di inclusione sia di esclusione (tramite istanze di filtri separate), l’esclusione viene valutata per prima. Per essere mantenuta, una tabella non deve corrispondere ad alcun modello di esclusione e deve corrispondere ad almeno un modello di inclusione.

ColumnFilter

Rimuove colonne specifiche dai dati delle righe durante l’acquisizione. È utile per le colonne variabili che cambiano a ogni scrittura e causerebbero differenze false.

PHP
use Merql\Filter\ColumnFilter;

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

Casi d’uso comuni

  • updated_at / modified_at timestamp che cambiano a ogni salvataggio.
  • revision contatori che si incrementano automaticamente.
  • session_token o altri campi temporanei.

Come funziona

Il filtro elimina le colonne indicate da ogni riga dopo aver calcolato la chiave della riga:

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

La chiave della riga (identità) viene calcolata a partire dalla riga non filtrata. Ciò significa che il filtro delle colonne non influisce mai sulle colonne di identità. Vengono filtrati solo i dati usati per il fingerprinting e il confronto delle differenze.

RowFilter

Filtra le singole righe usando una closure predicato. La closure riceve il nome della tabella e i dati completi della riga e restituisce true per includerla oppure false per escluderla.

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

Come funziona

Il metodo shouldInclude() viene chiamato per ogni riga durante l'acquisizione:

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

Le righe escluse non vengono sottoposte a fingerprint, non vengono salvate nello snapshot e non compaiono nelle differenze o nelle fusioni.

Combinare i filtri

Passate più filtri a capture(). Viene usato al massimo un filtro per tipo:

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

Ordine di elaborazione:

  1. TableFilter viene eseguito per primo e determina quali tabelle acquisire.
  2. Per ogni tabella, le righe vengono lette dal database.
  3. RowFilter viene eseguito su ogni riga ed esclude quelle che non corrispondono.
  4. La chiave della riga viene calcolata dalla riga non filtrata (con le colonne di identità intatte).
  5. ColumnFilter rimuove dai dati della riga le colonne ignorate.
  6. Il fingerprint viene calcolato dai dati della riga filtrati.

Quest'ordine assicura che le colonne di identità siano sempre disponibili per calcolare la chiave, anche se vengono poi rimosse dal filtro delle colonne.

Filtri e coerenza

È consigliabile usare gli stessi filtri per tutti e tre gli snapshot di una fusione (base, ours, theirs). Se si usano filtri diversi, righe o colonne potrebbero sembrare aggiunte o rimosse quando in realtà sono state filtrate in modo diverso.

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