عوامل التصفية
تحدد عوامل التصفية البيانات التي تُضمّن في اللقطة. استبعد جداول التخزين المؤقت، أو تجاهل أعمدة الطوابع الزمنية المتغيرة، أو تخطَّ الصفوف المؤقتة. تُطبّق عوامل التصفية أثناء التقاط اللقطة وتؤثر في جميع العمليات اللاحقة (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
يتحكم في الجداول التي تُضمّن في اللقطة. يدعم أنماط glob عبر PHP fnmatch().
استبعاد الجداول
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);