Fletning på celleniveau
Fletning på kolonneniveau registrerer, når begge sider har ændret den samme kolonne. Fletning på celleniveau går dybere og fletter indholdet i kolonnen. To personer, der redigerer forskellige linjer i et TEXT-felt eller forskellige nøgler i et JSON-objekt, kan flette uden konflikt.
use Merql\CellMerge\CellMergeConfig;
use Merql\Merge\ThreeWayMerge;
$config = CellMergeConfig::auto();
$merge = new ThreeWayMerge($config);
$result = $merge->merge($base, $ours, $theirs);
Aktivér fletning på celleniveau
Fletning på celleniveau er valgfri. Den kører kun i en ThreeWayMerge, der er konstrueret med en CellMergeConfig. Uden en sådan bliver enhver kolonne, som begge sider har ændret til forskellige værdier, en update_update-konflikt.
Facaden Merql tager ikke imod en konfiguration: Merql::merge(), Merql::patch() og Merql::plan() konstruerer new ThreeWayMerge() uden en, og kommandoen merge i CLI går gennem Merql::merge(). De fletter altid på kolonneniveau (#7).
Hvis du vil flette øjebliksbilleder, der er gemt af facaden eller CLI, med fletning på celleniveau, skal du indlæse dem og selv kalde ThreeWayMerge. Resultatet er en almindelig MergeResult, så facaden stadig kan anvende det, og MergePlanBuilder omdanner det til en fletteplan:
use Merql\CellMerge\CellMergeConfig;
use Merql\Merge\ThreeWayMerge;
use Merql\Merql;
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-1', $base, $ours, $theirs, $result);
Celleflettere kører kun for kolonner, som begge sider har ændret. Hvis kun den ene side har ændret en kolonne, bruges dens værdi uændret.
CellMergeConfig
CellMergeConfig knytter kolonner eller kolonnetyper til cellefletterimplementeringer. Fabrikken auto() leverer fornuftige standardindstillinger:
use Merql\CellMerge\CellMergeConfig;
use Merql\CellMerge\JsonCellMerger;
use Merql\CellMerge\TextCellMerger;
// Auto: column types containing "text" (TEXT, MEDIUMTEXT, LONGTEXT, ...) use
// TextCellMerger, column types containing "json" use JsonCellMerger.
$config = CellMergeConfig::auto();
// Custom: assign mergers to specific columns.
$config = (new CellMergeConfig())
->forColumn('posts.content', new TextCellMerger())
->forColumn('settings', new JsonCellMerger())
->forType('json', new JsonCellMerger());
Prioritet for valg af fletter:
- Fuldt kvalificeret kolonnenavn (
table.column). - Ukvalificeret kolonnenavn (
column). - Mønstermatch af kolonnetype (
str_containsuden forskel på store og små bogstaver). - Standard:
OpaqueCellMerger(rapporterer altid en konflikt, når værdierne afviger).
TextCellMerger
Fletter tekst med flere linjer ved hjælp af Myers-difference, samme algoritme som git bruger til filindhold. Hver linje behandles som en enhed, og ændringer af forskellige linjer flettes uden konflikt.
use Merql\CellMerge\TextCellMerger;
$merger = new TextCellMerger();
Eksempel: konfliktfri tekstfletning
Base: "line one\nline two\nline three"
Ours: "LINE ONE\nline two\nline three" // changed line 1
Theirs: "line one\nline two\nLINE THREE" // changed line 3
Der blev redigeret forskellige linjer. Fletningen giver "LINE ONE\nline two\nLINE THREE" uden konflikt.
Eksempel: tekstkonflikt
Base: "line one\nline two"
Ours: "changed by us\nline two" // changed line 1
Theirs: "changed by them\nline two" // also changed line 1
Begge sider ændrede den samme linje til forskellige værdier. Fletteren returnerer et konfliktresultat. Det flettede indhold indeholder konfliktmarkører, der minder om dem i git.
Sådan fungerer det
TextCellMerger bruger pitmasters ThreeWayMerge::merge(), som beregner en Myers-difference mellem base og hver side og derefter kombinerer de to redigeringsscripts. Hvis redigeringerne overlapper i det samme linjeområde, rapporterer den en konflikt.
JsonCellMerger
Fletter JSON-objekter ved at sammenligne nøgler på øverste niveau uafhængigt af hinanden. Hver nøgle flettes efter de almindelige trevejsregler.
use Merql\CellMerge\JsonCellMerger;
$merger = new JsonCellMerger();
Eksempel: konfliktfri JSON-fletning
// Base
{"name": "Alice", "role": "editor", "active": true}
// Ours: changed "role"
{"name": "Alice", "role": "admin", "active": true}
// Theirs: changed "name"
{"name": "Bob", "role": "editor", "active": true}
Der blev ændret forskellige nøgler. Det flettede resultat er:
{"name": "Bob", "role": "admin", "active": true}
Eksempel: JSON-konflikt
// Base
{"color": "red"}
// Ours
{"color": "blue"}
// Theirs
{"color": "green"}
Begge sider ændrede nøglen color til forskellige værdier. Det er en konflikt. Fletteren vælger som standard vores værdi og rapporterer én konflikt.
Regler for nøgler
| Base | Vores | Deres | Resultat |
|---|---|---|---|
| Nøgle uændret | Nøgle uændret | Brug base | |
| Nøgle uændret | Nøgle ændret | Brug deres | |
| Nøgle ændret | Nøgle uændret | Brug vores | |
| Nøgle ændret (ens) | Nøgle ændret (ens) | Brug værdien (enighed) | |
| Nøgle ændret (forskellig) | Nøgle ændret (forskellig) | Konflikt (standard: vores) | |
| Nøgle findes | Nøgle findes | Nøgle fjernet | Accepter fjernelse |
| Nøgle findes | Nøgle fjernet | Nøgle findes | Accepter fjernelse |
| Nøgle mangler | Nøgle tilføjet | Nøgle mangler | Accepter tilføjelse |
| Nøgle mangler | Nøgle mangler | Nøgle tilføjet | Accepter tilføjelse |
Indlejrede objekter sammenlignes som uigennemsigtige JSON-strenge, ikke rekursivt. Hvis et indlejret objekt afviger, sammenlignes hele værdien af den pågældende nøgle, ikke dens undernøgler.
Krav
Alle tre værdier skal være gyldige JSON-objekter eller -arrays. Hvis en værdi ikke er gyldig JSON eller er en skalar af typen JSON (streng, tal, boolesk værdi), falder fletteren tilbage til en konflikt.
OpaqueCellMerger
Standardfletteren, når der ikke er konfigureret en strategi for fletning på celleniveau. Den behandler kolonneværdien som en uigennemsigtig blok og rapporterer altid en konflikt, når de to sider er forskellige.
use Merql\CellMerge\OpaqueCellMerger;
$merger = new OpaqueCellMerger();
$result = $merger->merge($base, $ours, $theirs);
// $result->clean is always false when $ours !== $theirs
CellMergeResult
Alle celleflettere returnerer en CellMergeResult:
$result = $merger->merge($base, $ours, $theirs);
$result->clean; // bool: true if merge resolved cleanly
$result->value; // mixed: the merged value (or ours on conflict)
$result->conflicts; // int: number of conflicts within the cell
Fabrikmetoder:
CellMergeResult::resolved($value); // clean merge
CellMergeResult::conflict($oursValue, $n); // n conflicts, defaults to ours
Brugerdefinerede celleflettere
Implementér grænsefladen CellMerger for at tilføje din egen flette-strategi:
use Merql\CellMerge\CellMerger;
use Merql\CellMerge\CellMergeResult;
class YamlCellMerger implements CellMerger
{
public function merge(mixed $base, mixed $ours, mixed $theirs): CellMergeResult
{
// Parse YAML, merge keys, return result.
$merged = $this->mergeYaml($base, $ours, $theirs);
if ($merged['clean']) {
return CellMergeResult::resolved($merged['value']);
}
return CellMergeResult::conflict($ours);
}
}
$config = (new CellMergeConfig())
->forColumn('config_data', new YamlCellMerger());