Birleştirme Planları
Bir MergeResult, birleştirmenin çalıştırılabilir çıktısıdır. Bir MergePlan, bu çıktının incelenebilir biçimidir. Bir uygulamanın hedef veritabanına yazmadan önce veritabanı değişikliklerini göstermesi, hazırlaması, serileştirmesi veya seçerek uygulaması gerektiğinde bunu kullanın.
use Merql\Merql;
$plan = Merql::plan(
id: 'plan-2026-06-06',
base: 'base',
ours: 'ours',
theirs: 'theirs',
metadata: ['sandbox_id' => 'ow_123'],
);
Merql::plan(), adı belirtilen üç anlık görüntüyü yükler ve Merql::merge() gibi sütun düzeyinde birleştirir. TEXT ve JSON sütunları için hücre düzeyinde birleştirme kullanan bir plan oluşturmak üzere sonucu kendiniz oluşturup MergePlanBuilder öğesine iletin:
use Merql\CellMerge\CellMergeConfig;
use Merql\Merge\ThreeWayMerge;
use Merql\Plan\MergePlanBuilder;
use Merql\Snapshot\SnapshotStore;
$base = SnapshotStore::load('base');
$ours = SnapshotStore::load('ours');
$theirs = SnapshotStore::load('theirs');
$result = (new ThreeWayMerge(CellMergeConfig::auto()))->merge($base, $ours, $theirs);
$plan = (new MergePlanBuilder())->build('plan-2026-06-06', $base, $ours, $theirs, $result);
Plan şunları içerir:
- Oluşturulurken kullanılan anlık görüntü adları,
- İşlemlerin, çakışmaların, şema uyuşmazlıklarının, tabloların ve grupların özeti,
- Kararlı işlem kimlikleri,
- Kararlı değişiklik grubu kimlikleri,
- Satır kimlik sütunları ve kimlik değerleri,
- Her işlem için base, ours, theirs ve sonuç satır değerleri,
- İsteğe bağlı ana uygulama meta verileri,
- Plan karması,
- Şema sürümü.
Kararlı kimlikler
Aynı işlem içeriği için işlem kimlikleri deterministiktir. Tablo adından, satır anahtarından, işlem türünden, işlem kaynağından, değiştirilen sütunlardan ve sonuç değerlerinden türetilir.
Aynı grup içeriği için değişiklik grubu kimlikleri deterministiktir. Varsayılan oluşturucu her işlem için bir işlem grubu oluşturur. Ana uygulamalar, işlem listesinden daha büyük ve alana özgü gruplar oluşturabilir ve bunları yine aynı DTO biçimiyle serileştirebilir.
foreach ($plan->changeGroups as $group) {
echo $group->id . ': ' . implode(', ', $group->operationIds);
}
İşlem yapısı
Her MergePlanOperation inceleme ve geri alma için yeterli bağlamı korur.
$operation = $plan->operations[0];
$operation->id; // stable operation ID
$operation->type; // insert, update, delete
$operation->table; // canonical table name
$operation->rowKey; // encoded identity key
$operation->identityColumns; // columns used for identity
$operation->identityValues; // decoded identity values
$operation->source; // ours, theirs, or merged
$operation->baseRow; // row in base snapshot, or null
$operation->oursRow; // row in ours snapshot, or null
$operation->theirsRow; // row in theirs snapshot, or null
$operation->resultValues; // values the merge would write
$operation->changedColumns; // changed result columns
Seçimler
UI grupları hazırlarken ChangeGroupSelection kullanın. Uygulama yaparken veya geri alma yapıtları oluştururken bunu bir OperationSelection öğesine dönüştürün.
use Merql\Plan\ChangeGroupSelection;
use Merql\Plan\SelectedMergeResultFactory;
use Merql\Snapshot\SnapshotStore;
$selection = ChangeGroupSelection::fromIds([
$plan->changeGroups[0]->id,
]);
$operationSelection = $selection->toOperationSelection($plan);
$selectedResult = (new SelectedMergeResultFactory())->fromOperationSelection(
$plan,
$operationSelection,
SnapshotStore::load($plan->baseSnapshot),
);
Seçilen sonuç, yalnızca seçili işlemleri içeren temiz bir MergeResult olur. Merql::apply() veya Merql::applyGuarded() öğesine iletilebilir.
Hedefte Eksik Olanları Seçme
Bir plan her iki tarafın işlemlerini de içerir; çünkü birleştirme sonucu base'i birleştirilmiş duruma dönüştürür. Hedefte taraflardan biri zaten varsa yalnızca onda henüz bulunmayan işlemleri seçin. Theirs'i tutan bir hedefe, örneğin sandbox kopyasındaki düzenlemeleri alan canlı bir veritabanına, ours kaynağına sahip tüm işlemler ve her iki tarafın sütun değişikliklerini birleştiren merged güncellemeleri gönderilir:
use Merql\Plan\OperationSelection;
use Merql\Plan\SelectedMergeResultFactory;
use Merql\Snapshot\SnapshotStore;
// Rows with an unresolved conflict stay out of the selection.
$conflicted = [];
foreach ($plan->conflicts as $conflict) {
$conflicted[$conflict->table . "\0" . $conflict->rowKey] = true;
}
$ids = [];
foreach ($plan->operations as $operation) {
$missing = $operation->source === 'ours'
|| ($operation->source === 'merged' && $operation->type === 'update');
if ($missing && !isset($conflicted[$operation->table . "\0" . $operation->rowKey])) {
$ids[] = $operation->id;
}
}
$selected = (new SelectedMergeResultFactory())->fromOperationSelection(
$plan,
OperationSelection::fromIds($ids),
SnapshotStore::load($plan->baseSnapshot),
);
theirs kaynağına sahip işlemler ve merged silmeleri (her iki tarafın da sildiği satırlar) hedefte zaten bulunur.
Çakışmalar içeren bir birleştirmeden oluşturulan plan, her iki tarafın da güncellediği çakışmalı satırların her biri için yine bir işlem listeler. Sonuç değerleri, çakışan sütunda ours değerini tutar ve SelectedMergeResultFactory her seçim için temiz bir sonuç döndürür. İşlemin ve değişiklik grubunun conflictState alanları bu durumda da clean olarak görünür (#9); bu nedenle yukarıda belirtildiği gibi $plan->conflicts öğesini kendiniz denetleyin veya çakışmaları ConflictResolver ile çözerek planı çözümlenmiş sonuçtan MergePlanBuilder ile oluşturun. Seçimi canlı satır ön koşullarıyla yazmak için bkz. Korumalı Uygulama.
Serileştirme
Birleştirme planları ve seçimleri kararlı JSON serileştirmesine sahiptir. Daha sonraki bir uygulama adımında gözden geçirilmiş işlem kümesinin aynısının kullanılması gerekiyorsa serileştirilmiş planı saklayın.
use Merql\Plan\ChangeGroupSelection;
use Merql\Plan\MergePlanSerializer;
$json = MergePlanSerializer::toJson($plan);
$restored = MergePlanSerializer::fromJson($json);
$selectionJson = json_encode($selection->toArray(), JSON_THROW_ON_ERROR);
$selection = ChangeGroupSelection::fromArray(
json_decode($selectionJson, true, flags: JSON_THROW_ON_ERROR),
);
Takma Adlı Anlık Görüntüler
Birleştirme planları standart tablo adlarını kullanır. Fiziksel tablo adları ortamlar arasında farklıysa planlamadan önce bunları aynı standart ad altında kaydedin.
use Merql\Snapshot\SnapshotStore;
use Merql\Snapshot\Snapshotter;
$snapshotter = new Snapshotter($connection);
SnapshotStore::save($snapshotter->captureAliased('live', [
'wp_posts' => 'wp_posts',
]));
SnapshotStore::save($snapshotter->captureAliased('sandbox', [
'wp_onumia_abc_posts' => 'wp_posts',
]));
Anlık görüntüde saklanan şema, fiziksel tablonun sütunlarını, anahtarlarını, kimlik sütunlarını, satır anahtarlarını ve filtrelerini korurken standart tablo adını kullanır.