Фільтри
Фільтри визначають, які дані потрапляють до знімка. Виключайте таблиці кешу, ігноруйте мінливі стовпці з часовими мітками або пропускайте тимчасові рядки. Фільтри застосовуються під час створення знімка й впливають на всі подальші операції (порівняння, об’єднання, застосування).
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
Визначає, які таблиці потрапляють до знімка. Підтримує шаблони glob за допомогою fnmatch() від PHP.
Виключення таблиць
use Merql\Filter\TableFilter;
$filter = TableFilter::exclude(['sessions', 'cache_*', 'wp_*_log']);
Таблиці, що відповідають шаблону виключення, не потрапляють до знімка. Підстановний символ * відповідає будь-якій послідовності символів.
Додавання таблиць
$filter = TableFilter::include(['posts', 'comments', 'users']);
До знімка потрапляють лише таблиці, що відповідають шаблону включення. Усі інші виключаються.
Як це працює
Метод apply() фільтра приймає список назв таблиць і повертає відфільтровану вибірку:
$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']
Якщо задано шаблони включення й виключення (через окремі екземпляри фільтрів), спочатку перевіряються шаблони виключення. Щоб таблиця залишилася, вона не повинна відповідати жодному шаблону виключення й має відповідати принаймні одному шаблону включення.
ColumnFilter
Вилучає певні стовпці з даних рядків під час створення знімка. Корисно для мінливих стовпців, значення яких змінюються під час кожного запису й спричиняють хибні відмінності.
use Merql\Filter\ColumnFilter;
$filter = ColumnFilter::ignore(['updated_at', 'modified_date', 'last_login']);
Типові випадки використання
updated_at/modified_atчасові позначки, які змінюються під час кожного збереження.revisionлічильники, що автоматично збільшуються.session_tokenабо інші тимчасові поля.
Як це працює
Фільтр вилучає названі стовпці з кожного рядка після обчислення ключа рядка:
$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']
Ключ рядка (ідентичність) обчислюється на основі нефільтрованого рядка. Це означає, що фільтр стовпців ніколи не впливає на стовпці ідентичності. Фільтруються лише дані, що використовуються для обчислення відбитка та порівняння відмінностей.
RowFilter
Фільтрує окремі рядки за допомогою замикання-предиката. Замикання отримує назву таблиці та повні дані рядка й повертає true, щоб включити рядок, або false, щоб виключити його.
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;
});
Як це працює
Метод shouldInclude() викликається для кожного рядка під час знімання даних:
$include = $filter->shouldInclude('posts', ['id' => 1, 'status' => 'draft']);
// false
Виключені рядки не отримують відбитків, не зберігаються у знімку й не з’являються у відмінностях або злиттях.
Поєднання фільтрів
Передайте кілька фільтрів у capture(). Використовується не більш ніж один фільтр кожного типу:
$snapshot = $snapshotter->capture('baseline', filters: [
TableFilter::exclude(['cache_*']),
ColumnFilter::ignore(['updated_at']),
RowFilter::create(fn($table, $row) => ($row['active'] ?? '1') === '1'),
]);
Порядок обробки:
- Спочатку виконується TableFilter, який визначає, які таблиці знімати.
- Для кожної таблиці з бази даних зчитуються рядки.
- RowFilter виконується для кожного рядка й виключає ті, що не відповідають умовам.
- Ключ рядка обчислюється на основі нефільтрованого рядка (зі стовпцями ідентичності).
- ColumnFilter вилучає з даних рядка проігноровані стовпці.
- Відбиток обчислюється на основі відфільтрованих даних рядка.
Такий порядок гарантує, що стовпці ідентичності завжди доступні для обчислення ключа, навіть якщо пізніше їх вилучить фільтр стовпців.
Фільтри та узгодженість
Для всіх трьох знімків у злитті (base, ours, theirs) слід використовувати однакові фільтри. Якщо застосувати різні фільтри, може здатися, що рядки або стовпці додали чи вилучили, хоча насправді їх лише по-різному відфільтрували.
// 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);