PHP API-referencemateriale
Komplet reference til alle offentlige klasser og metoder i merql.
Merql (facade)
Merql\Merql er det statiske indgangspunkt til almindelige handlinger. Det indkapsler klasserne på lavere niveau og håndterer automatisk lagring af snapshots.
use Merql\Connection;
use Merql\Identity\IdentityRule;
use Merql\Identity\IdentityRuleSet;
use Merql\Merql;
$connection = Connection::sqlite(':memory:');
Merql::init($connection, identityRules: new IdentityRuleSet([
'options' => IdentityRule::natural(['option_name']),
]));
init(DatabaseConnection $connection, ?Driver $driver = null, ?IdentityRuleSet $identityRules = null): void
Initialisér facaden med en databaseforbindelse. Skal kaldes før
snapshot(), apply() eller applyGuarded(); kald den igen for at skifte database,
for eksempel for at tage snapshots af ours og theirs fra to forskellige kopier. Uden en
$driver kalder den DriverFactory::create(), som kaster en undtagelse for andre databasemotorer
end MySQL og SQLite, medmindre en driver er registreret. Angiv en driver for at tilsidesætte automatisk registrering eller et sæt identitetsregler for at tilsidesætte rækkeidentiteten pr. tabel under optagelse af snapshots.
snapshot(string $name, array $tables = []): Snapshot
Optag den aktuelle databasetilstand, og gem den på disk. Angiv en liste over tabelnavne for kun at tage snapshots af bestemte tabeller, eller udelad den for at tage snapshots af alle tabeller.
$snapshot = Merql::snapshot('baseline');
$snapshot = Merql::snapshot('baseline', ['posts', 'users']);
diff(string $base, string $current): Changeset
Indlæs to navngivne snapshots, og beregn ændringssættet mellem dem. Kræver ikke init(), da det arbejder ud fra gemte snapshots.
$changeset = Merql::diff('before', 'after');
merge(string $base, string $ours, string $theirs): MergeResult
Trevejssammenfletning af tre navngivne snapshots. Returnerer et resultat med konfliktfrie handlinger og eventuelle konflikter. Sammenfletter på kolonneniveau: facaden opretter ThreeWayMerge uden en CellMergeConfig, så sammenfletning på celleniveau ikke anvendes. Brug ThreeWayMerge direkte til det.
$result = Merql::merge('base', 'ours', 'theirs');
patch(string $base, string $changes): MergeResult
Tovejssammenfletning: anvend ændringer på grundlaget. Svarer til merge($base, $base, $changes). Giver altid et konfliktfrit resultat, da der ikke er samtidige redigeringer. Kun på kolonneniveau, ligesom merge().
$result = Merql::patch('base', 'changes');
apply(MergeResult $result): ApplyResult
Udfør et konfliktfrit sammenfletningsresultat på databasen, der blev sendt til init(). Kræver init(). Kaster ConflictException, hvis der stadig er uløste konflikter.
Hver handling i resultatet udføres, så hele resultatet af merge() kan kun anvendes konfliktfrit på en database, der stadig har grundlagstilstanden. Hvis databasen allerede har tilstanden fra den ene side, skal du anvende et udvalg af de handlinger, den mangler; se Beskyttet anvendelse.
$applied = Merql::apply($result);
echo $applied->rowsAffected();
plan(string $id, string $base, string $ours, string $theirs, array $metadata = []): MergePlan
Byg en sammenfletningsplan klar til UI ud fra tre navngivne snapshots. Planen indeholder stabile
handlings-ID'er, ID'er for ændringsgrupper, handlingskontekst, konflikter, skemaforskelle,
et resumé, metadata og en planhash. Sammenfletningen sker på kolonneniveau som i
merge(); send et cellesammenflettet resultat til MergePlanBuilder::build() for
sammenfletning på celleniveau.
$plan = Merql::plan('plan-1', 'base', 'ours', 'theirs', [
'source' => 'review-ui',
]);
applyGuarded(MergeResult $result, Snapshot $expectedLive): ApplyResult
Anvend et konfliktfrit sammenfletningsresultat med optimistiske forudsætninger for live-rækker. Opdateringer og
sletninger kræver, at de aktuelle live-rækker svarer til $expectedLive; ved indsættelser må
target-identiteten ikke allerede findes. $expectedLive er et snapshot af
databasen som mål (theirs, når ours overføres til den database, som theirs
blev taget fra). Hvis en kommando ikke påvirker nogen rækker, rulles transaktionen tilbage.
use Merql\Snapshot\SnapshotStore;
$applied = Merql::applyGuarded($selectedResult, SnapshotStore::load('theirs'));
reset(): void
Ryd de interne forbindelses- og Snapshotter-instanser. Bruges primært i test til at nulstille tilstanden mellem kørsler.
Forbindelse
Merql\Connection opretter forbindelsesadaptere med fornuftige standardindstillinger. PDO-forbindelser bruger undtagelser ved fejl, associativ hentetilstand, ingen emulerede forberedte sætninger og hentede værdier som strenge. mysqli-adapteren normaliserer hentede værdier til samme streng-eller-null-format.
mysql(string $host, string $database, string $username, string $password = '', int $port = 3306, string $charset = 'utf8mb4'): PdoDatabaseConnection
use Merql\Connection;
$connection = Connection::mysql('127.0.0.1', 'my_app', 'root', 'secret');
mysqli(string $host, string $database, string $username, string $password = '', int $port = 3306, string $charset = 'utf8mb4'): MysqliDatabaseConnection
$connection = Connection::mysqli('127.0.0.1', 'my_app', 'root', 'secret');
sqlite(string $path = ':memory:'): PdoDatabaseConnection
Opretter en SQLite-forbindelse. Aktiverer automatisk fremmednøgler via PRAGMA foreign_keys = ON.
$connection = Connection::sqlite('/var/data/app.sqlite');
$connection = Connection::sqlite(':memory:');
fromDsn(string $dsn, string $username = '', string $password = ''): PdoDatabaseConnection
Opret forbindelse med en vilkårlig PDO DSN-streng. merql leveres kun med drivere til mysql og sqlite; andre DSN'er opretter en forbindelse, men Merql::init(), Snapshotter og applikatorerne kaster Unsupported database driver, medmindre en driver er registreret med DriverFactory::register().
$connection = Connection::fromDsn('mysql:host=localhost;dbname=app', 'root', 'pass');
fromPdo(PDO $pdo): PdoDatabaseConnection
Ombryd en eksisterende PDO-instans.
fromMysqli(mysqli $mysqli, string $charset = 'utf8mb4'): MysqliDatabaseConnection
Ombryd en eksisterende mysqli-instans.
Adapterkontrakt
Alle adaptere implementerer Merql\Database\DatabaseConnection:
interface DatabaseConnection
{
public function driverName(): string;
public function execute(string $sql, array $params = []): int;
public function query(string $sql, array $params = []): array;
public function scalar(string $sql, array $params = []): ?string;
public function beginTransaction(): void;
public function commit(): void;
public function rollBack(): void;
public function lastInsertId(): string;
}
execute(), query() og scalar() accepterer positionelle list<scalar|null>
parametre for pladsholdere af typen ?. query() returnerer
list<array<string, scalar|null>>; værdier normaliseres til samme
streng-eller-null-format på tværs af PDO- og mysqli-adaptere.
Snapshotter
Merql\Snapshot\Snapshotter optager databasetilstanden. I modsætning til facaden giver den dig fuld kontrol over filtre og gemmer ikke automatisk.
__construct(DatabaseConnection $connection, ?Driver $driver = null, ?IdentityRuleSet $identityRules = null)
Driveren registreres automatisk ud fra forbindelsens identitet, hvis den ikke angives. Angiv et
IdentityRuleSet, når tabelspecifik rækkeidentitet skal tilsidesætte skemaets
standardindstillinger.
capture(string $name, array $tables = [], array $filters = []): Snapshot
Optag den aktuelle tilstand. Angiv tabelnavne for at begrænse omfanget. Angiv filterobjekter for at udelukke tabeller, kolonner eller rækker.
use Merql\Snapshot\Snapshotter;
use Merql\Filter\TableFilter;
use Merql\Filter\ColumnFilter;
use Merql\Filter\RowFilter;
use Merql\Identity\IdentityRule;
use Merql\Identity\IdentityRuleSet;
$snapshotter = new Snapshotter(
$connection,
identityRules: new IdentityRuleSet([
'wp_options' => IdentityRule::natural(['option_name']),
]),
);
// All tables.
$snapshot = $snapshotter->capture('full');
// Specific tables with filters.
$snapshot = $snapshotter->capture('filtered', ['posts', 'users'], [
TableFilter::exclude(['cache_*', 'sessions']),
ColumnFilter::ignore(['updated_at', 'created_at']),
RowFilter::create(fn(string $table, array $row) => $row['status'] !== 'trash'),
]);
captureAliased(string $name, array $physicalToCanonicalTableMap, array $filters = []): Snapshot
Optag fysiske tabeller under kanoniske tabelnavne. Brug dette, når den samme logiske tabel har forskellige fysiske navne på tværs af miljøer.
$snapshot = $snapshotter->captureAliased('sandbox', [
'wp_onumia_abcd_posts' => 'wp_posts',
'wp_onumia_abcd_postmeta' => 'wp_postmeta',
]);
Det resulterende snapshot gemmer kanoniske tabelnavne, samtidig med at det bevarer det fysiske tabelskema, konfigurerede identitetskolonner, rækkenøgler og filtre.
fromData(string $name, array $tableData): Snapshot (statisk)
Byg et snapshot ud fra rådata uden en databaseforbindelse. Nyttigt til test eller ved import af data fra en anden kilde.
use Merql\Snapshot\Snapshotter;
use Merql\Snapshot\TableSnapshotData;
use Merql\Schema\TableSchema;
$schema = new TableSchema('posts', ['id' => 'int', 'title' => 'varchar'], ['id']);
$snapshot = Snapshotter::fromData('test', [
'posts' => new TableSnapshotData($schema, [
['id' => '1', 'title' => 'Hello'],
['id' => '2', 'title' => 'World'],
], ['id']),
]);
Snapshot
Merql\Snapshot\Snapshot er et skrivebeskyttet værdiobjekt, der repræsenterer en fuldstændig databasetilstand.
$snapshot->name; // string: snapshot identifier
$snapshot->tables; // array<string, TableSnapshot>
$snapshot->tableNames(); // list<string>
$snapshot->hasTable('posts'); // bool
$snapshot->getTable('posts'); // ?TableSnapshot
TableSnapshot
Merql\Snapshot\TableSnapshot indeholder én tabels rækker, fingeraftryk og skema.
$table = $snapshot->getTable('posts');
$table->schema; // TableSchema
$table->identityColumns; // list<string>: columns used for row identity
$table->fingerprints; // array<string, string>: row key to hash
$table->rows; // array<string, array<string, mixed>>
$table->rowKeys(); // list<string>
$table->rowCount(); // int
$table->hasRow('42'); // bool
$table->getRow('42'); // ?array<string, mixed>
$table->getFingerprint('42'); // ?string
TableSnapshotData
Merql\Snapshot\TableSnapshotData er inputdata til Snapshotter::fromData().
use Merql\Snapshot\TableSnapshotData;
use Merql\Schema\TableSchema;
$data = new TableSnapshotData(
schema: new TableSchema('posts', ['id' => 'int', 'title' => 'varchar'], ['id']),
rows: [
['id' => '1', 'title' => 'First Post'],
],
identityColumns: ['id'],
);
IdentityRule
Merql\Identity\IdentityRule definerer de kolonner, der bruges til at opbygge rækkenøgler.
use Merql\Identity\IdentityRule;
$primary = IdentityRule::primary(['id']);
$natural = IdentityRule::natural(['option_name']);
$composite = IdentityRule::composite(['object_id', 'term_taxonomy_id']);
$content = IdentityRule::content(['name', 'value']);
$key = $natural->key(['option_name' => 'siteurl']);
// "siteurl"
forSchema(TableSchema $schema): IdentityRule (statisk)
Find standardidentitetsreglen ud fra skemaet: primærnøgle, første unikke nøgle, derefter fallback til indhold.
toArray(): array
Serialisér reglen som ['type' => string, 'columns' => list<string>].
fromArray(array $data): IdentityRule (statisk)
Opret en regel ud fra serialiserede data.
IdentityRuleSet
Merql\Identity\IdentityRuleSet gemmer tabelspecifikke tilsidesættelser af identitet.
use Merql\Identity\IdentityRule;
use Merql\Identity\IdentityRuleSet;
$rules = new IdentityRuleSet([
'wp_options' => IdentityRule::natural(['option_name']),
]);
$rule = $rules->ruleFor($schema);
with(string $table, IdentityRule $rule): IdentityRuleSet
Returner et nyt regelsæt med én tilføjet tabeltilsidesættelse.
conflictsFor(string $table, IdentityRule $rule, array $rows): array
Returner IdentityConflict-poster, når flere rækker giver samme nøgle for en
regel.
toArray(): array
Serialisér tabelregler som et JSON-sikkert array.
fromArray(array $data): IdentityRuleSet (statisk)
Opret et regelsæt ud fra serialiserede data.
SnapshotStore
Merql\Snapshot\SnapshotStore gemmer og indlæser snapshots som JSON-filer.
setDirectory(string $directory): void
Angiv lagermappen. Standard er .merql/snapshots.
save(Snapshot $snapshot): void
Skriv et snapshot til disk.
load(string $name): Snapshot
Indlæs et snapshot efter navn. Kaster SnapshotException, hvis det ikke findes.
exists(string $name): bool
Kontrollér, om en snapshotfil findes.
delete(string $name): void
Fjern en snapshotfil.
Differ
Merql\Diff\Differ sammenligner to snapshots og opretter et ændringssæt.
diff(Snapshot $base, Snapshot $current): Changeset
use Merql\Diff\Differ;
$differ = new Differ();
$changeset = $differ->diff($baseSnapshot, $currentSnapshot);
valuesEqual(mixed $a, mixed $b): bool (statisk)
Sammenlign to værdier ved at tvinge dem til strenge. NULL behandles som en særskilt værdi: NULL === NULL er sand, NULL === '' er falsk.
Ændringssæt
Merql\Diff\Changeset er en skrivebeskyttet samling af handlinger på rækkeniveau.
$changeset->inserts(); // list<RowInsert>
$changeset->updates(); // list<RowUpdate>
$changeset->deletes(); // list<RowDelete>
$changeset->isEmpty(); // bool
$changeset->count(); // int: total operations
$changeset->forTable('posts'); // Changeset: filtered to one table
RowInsert, RowUpdate, RowDelete
Skrivebeskyttede værdiobjekter, der repræsenterer ændringer af enkelte rækker.
RowInsert
$insert->table; // string
$insert->rowKey; // string
$insert->values; // array<string, mixed>
RowUpdate
$update->table; // string
$update->rowKey; // string
$update->columnDiffs; // list<ColumnDiff>
$update->fullRow; // array<string, mixed>: complete current row
$update->columnDiffMap(); // array<string, ColumnDiff>: keyed by column name
RowDelete
$delete->table; // string
$delete->rowKey; // string
$delete->oldValues; // array<string, mixed>: values before deletion
ColumnDiff
Merql\Diff\ColumnDiff repræsenterer en enkelt kolonneændring i en rækkeopdatering.
$diff->column; // string
$diff->oldValue; // mixed
$diff->newValue; // mixed
ThreeWayMerge
Merql\Merge\ThreeWayMerge er den centrale sammenfletningsalgoritme.
__construct(?CellMergeConfig $cellMergeConfig = null)
Angiv en CellMergeConfig for at aktivere sammenfletning på celleniveau for TEXT- og JSON-kolonner.
use Merql\Merge\ThreeWayMerge;
use Merql\CellMerge\CellMergeConfig;
// Default: column-level merge only.
$merge = new ThreeWayMerge();
// With cell-level merge for TEXT and JSON columns.
$merge = new ThreeWayMerge(CellMergeConfig::auto());
merge(Snapshot $base, Snapshot $ours, Snapshot $theirs): MergeResult
Udfør en trevejssammenfletning. Beregner ændringssæt internt (fra base til ours og fra base til theirs) og sammenfletter dem.
$result = $merge->merge($baseSnapshot, $oursSnapshot, $theirsSnapshot);
patch(Snapshot $base, Snapshot $changes): MergeResult
Genvej til tovejssammenfletning. Svarer til merge($base, $base, $changes).
schemaMismatches(): array
Returnerer SchemaException[] for alle skemaforskelle, der blev registreret under den seneste sammenfletning (kolonner tilføjet eller fjernet mellem snapshots).
MergeResult
Merql\Merge\MergeResult er et skrivebeskyttet værdiobjekt, der indeholder resultatet af sammenfletningen.
$result->isClean(); // bool: no conflicts
$result->operations(); // list<MergeOperation>
$result->conflicts(); // list<Conflict>
$result->operationCount(); // int
$result->conflictCount(); // int
$result->baseSnapshot(); // ?Snapshot
$result->schemaMismatches(); // list<SchemaException>
$result->hasSchemaMismatches(); // bool
MergePlan
Merql\Plan\MergePlan er en serialiserbar reviewmodel for en sammenfletning.
$plan->id; // string
$plan->baseSnapshot; // string
$plan->oursSnapshot; // string
$plan->theirsSnapshot; // string
$plan->summary; // MergePlanSummary
$plan->changeGroups; // list<MergePlanChangeGroup>
$plan->operations; // list<MergePlanOperation>
$plan->conflicts; // list<MergePlanConflict>
$plan->schemaMismatches; // list<string>
$plan->hash; // string
$plan->metadata; // array<string, mixed>
Brug MergePlanSerializer::toJson() og ::fromJson() til stabile JSON-ture.
Udvalg
ChangeGroupSelection gemmer trinvist tilføjede ID'er for ændringsgrupper. Konvertér den til en
OperationSelection, når du opbygger udvalgte sammenfletningsresultater eller tilbagerulningsplaner.
use Merql\Plan\ChangeGroupSelection;
use Merql\Plan\SelectedMergeResultFactory;
$selection = ChangeGroupSelection::fromIds([$groupId]);
$operationSelection = $selection->toOperationSelection($plan);
$selected = (new SelectedMergeResultFactory())
->fromOperationSelection($plan, $operationSelection);
RollbackPlan
Merql\Rollback\RollbackPlan gemmer inverse handlinger og forventninger til afvigelser
for en udvalgt anvendelse.
use Merql\Rollback\RollbackPlanBuilder;
use Merql\Rollback\RollbackPlanSerializer;
$rollback = (new RollbackPlanBuilder())->build(
'rollback-1',
$plan,
$operationSelection,
$liveBeforeRows,
);
$json = RollbackPlanSerializer::toJson($rollback);
Brug RollbackDrift før rollback, og brug derefter RollbackPlanApplier til at køre de inverse operationer.
MergeOperation
Merql\Merge\MergeOperation er en enkelt afklaret operation fra sammenfletningen.
$op->type; // string: 'insert' | 'update' | 'delete'
$op->table; // string
$op->rowKey; // string
$op->values; // array<string, mixed>
$op->source; // string: 'ours' | 'theirs' | 'merged'
Typekonstanter:
MergeOperation::TYPE_INSERT; // 'insert'
MergeOperation::TYPE_UPDATE; // 'update'
MergeOperation::TYPE_DELETE; // 'delete'
Konflikt
Merql\Merge\Conflict repræsenterer en uafklaret sammenfletningskonflikt.
$conflict->table(); // string
$conflict->rowKey(); // string
$conflict->type(); // string: 'update_update' | 'update_delete' | 'delete_update' | 'insert_insert'
$conflict->column(); // ?string (null for structural conflicts)
$conflict->oursValue(); // mixed
$conflict->theirsValue(); // mixed
$conflict->baseValue(); // mixed
$conflict->primaryKey(['id']); // array<string, string>: decoded from rowKey
Konflikttyper
| Type | Betydning |
|---|---|
update_update |
Begge sider ændrede den samme kolonne til forskellige værdier |
update_delete |
Vores side opdaterede en række, som deres side slettede |
delete_update |
Vores side slettede en række, som deres side opdaterede |
insert_insert |
Begge sider indsatte en række med samme primærnøgle |
ConflictResolver
Merql\Merge\ConflictResolver anvender en løsningspolitik på alle konflikter i resultatet af en sammenfletning.
resolve(MergeResult $result, ConflictPolicy $policy): MergeResult (statisk)
Returnerer en ny MergeResult med konflikter løst i henhold til politikken.
use Merql\Merge\ConflictResolver;
use Merql\Merge\ConflictPolicy;
// Accept all "theirs" values when conflicts arise.
$resolved = ConflictResolver::resolve($result, ConflictPolicy::TheirsWins);
// Accept all "ours" values.
$resolved = ConflictResolver::resolve($result, ConflictPolicy::OursWins);
// Return unchanged (for manual inspection).
$resolved = ConflictResolver::resolve($result, ConflictPolicy::Manual);
ConflictPolicy
Merql\Merge\ConflictPolicy er en backed enum med tre cases.
use Merql\Merge\ConflictPolicy;
ConflictPolicy::OursWins; // Resolve all conflicts in favor of "ours"
ConflictPolicy::TheirsWins; // Resolve all conflicts in favor of "theirs"
ConflictPolicy::Manual; // Leave conflicts unresolved for manual handling
ColumnMerge
Merql\Merge\ColumnMerge udfører sammenfletningslogik pr. kolonne for en enkelt række. Bruges internt af ThreeWayMerge.
merge(string $table, string $rowKey, array $base, array $ours, array $theirs, ?CellMergeConfig $cellMergeConfig = null, array $columnTypes = []): array (statisk)
Returnerer ['values' => array, 'conflicts' => list<Conflict>].
use Merql\Merge\ColumnMerge;
$result = ColumnMerge::merge(
'posts',
'42',
['title' => 'Hello', 'status' => 'draft'], // base
['title' => 'Hello', 'status' => 'published'], // ours
['title' => 'New Title', 'status' => 'draft'], // theirs
);
// $result['values'] = ['title' => 'New Title', 'status' => 'published']
// $result['conflicts'] = [] (clean merge)
Udfører
Merql\Apply\Applier udfører et sammenfletningsresultat på en database.
__construct(DatabaseConnection $connection, ?Driver $driver = null)
apply(MergeResult $result, ?Snapshot $base = null): ApplyResult
Udfører alle operationer i en enkelt transaktion. Ruller tilbage ved enhver fejl og rapporterer den i ApplyResult::errors() i stedet for at kaste den. Kaster ConflictException, hvis resultatet indeholder uafklarede konflikter.
use Merql\Apply\Applier;
$applier = new Applier($connection);
$applied = $applier->apply($result);
echo "Rows affected: {$applied->rowsAffected()}\n";
if ($applied->hasErrors()) {
print_r($applied->errors());
}
Fremmednøglerækkefølgen håndteres automatisk: Indsættelser sorteres efter afhængigheder, og sletninger sorteres i omvendt afhængighedsrækkefølge.
ApplyResult
Merql\Apply\ApplyResult er et skrivebeskyttet værdiobjekt, som returneres af udføreren.
$applied->rowsAffected(); // int
$applied->errors(); // list<string>
$applied->hasErrors(); // bool
Efter en tilbagerullet anvendelse tæller rowsAffected() stadig de sætninger, der blev kørt før fejlen (#4). Kontrollér hasErrors(), før du stoler på tallet.
DryRun
Merql\Apply\DryRun genererer menneskeligt læsbare SQL uden at udføre noget.
generate(MergeResult $result, ?Snapshot $base = null, array $fkDependencies = [], ?Driver $driver = null): array (statisk)
Returnerer en liste med SQL-strenge, hvor værdierne er indsat (kun til visning).
use Merql\Apply\DryRun;
$statements = DryRun::generate($result);
foreach ($statements as $sql) {
echo "{$sql};\n";
}
// Output:
// INSERT INTO `posts` (`id`, `title`) VALUES ('10', 'New Post');
// UPDATE `posts` SET `title` = 'Updated' WHERE `id` = '5';
// DELETE FROM `comments` WHERE `id` = '3';
SqlGenerator
Merql\Apply\SqlGenerator genererer parametriserede SQL-sætninger. Bruges internt af både Applier og DryRun.
generate(MergeResult $result, ?Snapshot $base = null, array $fkDependencies = [], ?Driver $driver = null): array (statisk)
Returnerer list<array{sql: string, params: list<scalar|null>}>.
use Merql\Apply\SqlGenerator;
$statements = SqlGenerator::generate($result);
foreach ($statements as $stmt) {
$connection->execute($stmt['sql'], $stmt['params']);
}
CellMergeConfig
Merql\CellMerge\CellMergeConfig konfigurerer sammenfletningsstrategier på celleniveau for bestemte kolonner eller kolonnetyper.
auto(): self (statisk)
Praktisk factory, der tildeler TextCellMerger til TEXT/LONGTEXT-kolonner og JsonCellMerger til JSON-kolonner.
use Merql\CellMerge\CellMergeConfig;
$config = CellMergeConfig::auto();
forColumn(string $column, CellMerger $merger): self
Tildel en sammenfletter til en bestemt kolonne. Brug table.column til kvalificerede navne eller blot column til alle tabeller.
use Merql\CellMerge\CellMergeConfig;
use Merql\CellMerge\TextCellMerger;
$config = (new CellMergeConfig())
->forColumn('posts.content', new TextCellMerger())
->forColumn('description', new TextCellMerger());
forType(string $typePattern, CellMerger $merger): self
Tildel en sammenfletter til alle kolonner, der matcher et typemønster (uafhængigt af store og små bogstaver, delstrengsmatch).
use Merql\CellMerge\CellMergeConfig;
use Merql\CellMerge\JsonCellMerger;
$config = (new CellMergeConfig())
->forType('json', new JsonCellMerger());
getMerger(string $table, string $column, string $columnType = ''): CellMerger
Find sammenfletteren for en given tabel, kolonne og type. Prioritet: kvalificeret kolonnenavn, ukvalificeret kolonnenavn, typemønster, standard (opaque).
CellMerger (grænseflade)
Merql\CellMerge\CellMerger er grænsefladen for sammenfletningsstrategier på celleniveau.
use Merql\CellMerge\CellMerger;
use Merql\CellMerge\CellMergeResult;
interface CellMerger
{
public function merge(mixed $base, mixed $ours, mixed $theirs): CellMergeResult;
}
Der findes tre indbyggede implementeringer.
TextCellMerger
Merql\CellMerge\TextCellMerger sammenfletter tekst med flere linjer ved hjælp af en trevejssammenligning linje for linje (samme algoritme, som git bruger til filindhold). Når begge sider redigerer forskellige linjer, lykkes sammenfletningen uden konflikter. Når begge sider redigerer den samme linje forskelligt, rapporteres en konflikt.
use Merql\CellMerge\TextCellMerger;
$merger = new TextCellMerger();
$result = $merger->merge(
"line 1\nline 2\nline 3",
"line 1\nline 2 modified\nline 3",
"line 1\nline 2\nline 3 modified",
);
// $result->clean === true
// $result->value === "line 1\nline 2 modified\nline 3 modified"
JsonCellMerger
Merql\CellMerge\JsonCellMerger sammenfletter JSON-værdier ved at sammenligne nøgler på øverste niveau uafhængigt. Hver nøgle sammenflettes med trevejslogik. Indlejrede objekter sammenlignes som opaque JSON-strenge (de sammenflettes ikke rekursivt).
use Merql\CellMerge\JsonCellMerger;
$merger = new JsonCellMerger();
$result = $merger->merge(
'{"a": 1, "b": 2}',
'{"a": 10, "b": 2}', // changed "a"
'{"a": 1, "b": 20}', // changed "b"
);
// $result->clean === true
// $result->value === '{"a":10,"b":20}'
OpaqueCellMerger
Merql\CellMerge\OpaqueCellMerger er standarden. Den behandler værdier som opaque strenge og rapporterer altid en konflikt, når de er forskellige.
CellMergeResult
Merql\CellMerge\CellMergeResult er returtypen for alle celle-sammenflettere.
$result->clean; // bool: true if merge succeeded
$result->value; // mixed: merged value (or ours on conflict)
$result->conflicts; // int: number of conflicts
// Factory methods.
CellMergeResult::resolved($value); // clean merge
CellMergeResult::conflict($oursValue, $n); // conflict with count
TableSchema
Merql\Schema\TableSchema er en skrivebeskyttet repræsentation af tabelstrukturen.
use Merql\Schema\TableSchema;
$schema = new TableSchema(
name: 'posts',
columns: ['id' => 'int', 'title' => 'varchar(255)', 'content' => 'text'],
primaryKey: ['id'],
uniqueKeys: [['slug']],
);
$schema->name; // string
$schema->columns; // array<string, string>: name to type
$schema->primaryKey; // list<string>
$schema->uniqueKeys; // list<list<string>>
$schema->hasPrimaryKey(); // bool
$schema->hasUniqueKeys(); // bool
$schema->columnNames(); // list<string>
Driversystem
merql bruger et system med udskiftelige drivere til at abstrahere databasespecifikke operationer. Drivere registreres automatisk ud fra forbindelsens driveridentitet.
Driver (grænseflade)
Merql\Driver\Driver definerer den kontrakt, som alle databasedrivere implementerer.
interface Driver
{
public function quoteIdentifier(string $name): string;
public function listTables(DatabaseConnection $connection): array;
public function readSchema(DatabaseConnection $connection, string $table): TableSchema;
public function readForeignKeys(DatabaseConnection $connection): array;
public function selectAll(string $table): string;
}
Indbyggede implementeringer: MysqlDriver og SqliteDriver.
DriverFactory
Merql\Driver\DriverFactory registrerer automatisk driveren ud fra en forbindelse.
use Merql\Driver\DriverFactory;
$driver = DriverFactory::create($connection);
Registrer en tilpasset driver til andre databaser:
DriverFactory::register('pgsql', MyPostgresDriver::class);
Filtre
TableFilter
Merql\Filter\TableFilter inkluderer eller udelukker tabeller ved hjælp af globmønstre.
use Merql\Filter\TableFilter;
$filter = TableFilter::exclude(['cache_*', 'sessions', 'temp_*']);
$filter = TableFilter::include(['posts', 'users', 'comments']);
ColumnFilter
Merql\Filter\ColumnFilter fjerner bestemte kolonner fra snapshots.
use Merql\Filter\ColumnFilter;
$filter = ColumnFilter::ignore(['updated_at', 'created_at', 'modified_date']);
RowFilter
Merql\Filter\RowFilter filtrerer rækker ved hjælp af en prædikatfunktion.
use Merql\Filter\RowFilter;
$filter = RowFilter::create(function (string $table, array $row): bool {
// Exclude trashed posts.
if ($table === 'posts' && ($row['status'] ?? '') === 'trash') {
return false;
}
return true;
});
Undtagelser
SnapshotException
Merql\Exceptions\SnapshotException kastes, når et snapshot ikke kan findes eller har et ugyldigt navn.
SnapshotException::notFound('baseline', '/path/to/baseline.json');
MergeException
Merql\Exceptions\MergeException kastes, når et påkrævet snapshot mangler til en sammenfletning.
MergeException::snapshotRequired('base');
ConflictException
Merql\Exceptions\ConflictException kastes, når der forsøges at anvende et sammenfletningsresultat med uafklarede konflikter.
ConflictException::unresolved(3);
// Message: "Cannot apply merge with 3 unresolved conflict(s)"
SchemaException
Merql\Exceptions\SchemaException kastes (eller indsamles), når skemaerne er forskellige mellem snapshots.
SchemaException::mismatch('posts', 'column "tags" exists in current but not in base');
Skemaforskelle stopper ikke sammenfletningen. De indsamles og kan ses via $result->schemaMismatches().