Ga naar de inhoud

Referentie voor PHP API

Volledige referentie voor alle openbare klassen en methoden in merql.

Merql (facade)

Merql\Merql is het statische toegangspunt voor veelgebruikte bewerkingen. Het vormt een laag om de onderliggende klassen en beheert het opslaan van snapshots automatisch.

PHP
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

Initialiseer de facade met een databaseverbinding. Dit moet gebeuren voordat u snapshot(), apply() of applyGuarded() aanroept; roep deze functie opnieuw aan om van database te wisselen, bijvoorbeeld om ours en theirs uit twee verschillende kopieën als snapshot op te slaan. Zonder $driver roept de functie DriverFactory::create() aan. Deze geeft een fout voor engines anders dan MySQL en SQLite, tenzij er een driver is geregistreerd. Geef een driver mee om automatische detectie te overschrijven, of een set identiteitsregels om de rij-identiteit per tabel tijdens het vastleggen van een snapshot te overschrijven.

snapshot(string $name, array $tables = []): Snapshot

Leg de huidige databasestatus vast en sla deze op schijf op. Geef een array met tabelnamen mee om een snapshot van specifieke tabellen te maken, of laat deze weg voor alle tabellen.

PHP
$snapshot = Merql::snapshot('baseline');
$snapshot = Merql::snapshot('baseline', ['posts', 'users']);

diff(string $base, string $current): Changeset

Laad twee snapshots op naam en bereken de wijzigingen tussen deze snapshots. init() is niet vereist, omdat de functie met opgeslagen snapshots werkt.

PHP
$changeset = Merql::diff('before', 'after');

merge(string $base, string $ours, string $theirs): MergeResult

Voert een three-way merge uit van drie snapshots op naam. Geeft een resultaat met conflictvrije bewerkingen en eventuele conflicten. De merge wordt op kolomniveau uitgevoerd: de facade bouwt ThreeWayMerge zonder CellMergeConfig, dus er wordt geen merge op celniveau toegepast. Gebruik hiervoor rechtstreeks ThreeWayMerge.

PHP
$result = Merql::merge('base', 'ours', 'theirs');

patch(string $base, string $changes): MergeResult

Two-way merge: pas wijzigingen toe op de basis. Gelijk aan merge($base, $base, $changes). Levert altijd een conflictvrij resultaat op, omdat er geen gelijktijdige bewerkingen zijn. Alleen op kolomniveau, net als merge().

PHP
$result = Merql::patch('base', 'changes');

apply(MergeResult $result): ApplyResult

Voer een conflictvrij mergeresultaat uit op de database die aan init() is doorgegeven. init() is vereist. Geeft ConflictException als er onopgeloste conflicten zijn.

Elke bewerking in het resultaat wordt uitgevoerd. Daarom wordt het volledige resultaat van merge() alleen correct toegepast op een database die nog de basisstatus bevat. Als een database al een van beide zijden bevat, pas dan een selectie toe van de bewerkingen die daarin ontbreken; zie Selectief toepassen.

PHP
$applied = Merql::apply($result);
echo $applied->rowsAffected();

plan(string $id, string $base, string $ours, string $theirs, array $metadata = []): MergePlan

Bouw een mergeplan dat klaar is voor UI op basis van drie snapshots op naam. Het plan bevat stabiele bewerkings-ID's, wijzigingsgroep-ID's, bewerkingscontext, conflicten, schemamismatches, een samenvatting, metagegevens en een planhash. De merge wordt op kolomniveau uitgevoerd, net als bij merge(); geef een resultaat dat op celniveau is samengevoegd door aan MergePlanBuilder::build() voor een merge op celniveau.

PHP
$plan = Merql::plan('plan-1', 'base', 'ours', 'theirs', [
    'source' => 'review-ui',
]);

applyGuarded(MergeResult $result, Snapshot $expectedLive): ApplyResult

Pas een conflictvrij mergeresultaat toe met optimistische voorwaarden voor live rijen. Voor updates en verwijderingen moeten de huidige live rijen overeenkomen met $expectedLive; bij invoegingen mag de doelidentiteit nog niet bestaan. $expectedLive is een snapshot van de doeldatabase (theirs, wanneer ours wordt gepromoveerd naar de database waarvan theirs afkomstig is). Elke instructie die nul rijen beïnvloedt, maakt de transactie ongedaan.

PHP
use Merql\Snapshot\SnapshotStore;

$applied = Merql::applyGuarded($selectedResult, SnapshotStore::load('theirs'));

reset(): void

Wis de interne verbinding en de Snapshotter-instanties. Dit wordt voornamelijk gebruikt in tests om de status tussen uitvoeringen opnieuw in te stellen.


Verbinding

Merql\Connection bouwt verbindingsadapters met verstandige standaardinstellingen. PDO-verbindingen gebruiken uitzonderingen bij fouten, een associatieve ophaalmodus, geen geëmuleerde voorbereide instructies en opgehaalde waarden als tekenreeksen. De mysqli-adapter normaliseert opgehaalde waarden naar dezelfde vorm van tekenreeks of null.

mysql(string $host, string $database, string $username, string $password = '', int $port = 3306, string $charset = 'utf8mb4'): PdoDatabaseConnection

PHP
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

PHP
$connection = Connection::mysqli('127.0.0.1', 'my_app', 'root', 'secret');

sqlite(string $path = ':memory:'): PdoDatabaseConnection

Maakt een verbinding met SQLite. Schakelt automatisch foreign keys in via PRAGMA foreign_keys = ON.

PHP
$connection = Connection::sqlite('/var/data/app.sqlite');
$connection = Connection::sqlite(':memory:');

fromDsn(string $dsn, string $username = '', string $password = ''): PdoDatabaseConnection

Maak verbinding met een PDO DSN-tekenreeks. merql bevat alleen drivers voor mysql en sqlite; andere DSN's openen wel een verbinding, maar Merql::init(), Snapshotter en de appliers geven Unsupported database driver, tenzij er een driver is geregistreerd met DriverFactory::register().

PHP
$connection = Connection::fromDsn('mysql:host=localhost;dbname=app', 'root', 'pass');

fromPdo(PDO $pdo): PdoDatabaseConnection

Wikkel een bestaande PDO-instantie in.

fromMysqli(mysqli $mysqli, string $charset = 'utf8mb4'): MysqliDatabaseConnection

Wikkel een bestaande mysqli-instantie in.

Adaptercontract

Alle adapters implementeren Merql\Database\DatabaseConnection:

PHP
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() en scalar() accepteren positionele list<scalar|null>-parameters voor ?-placeholders. query() geeft list<array<string, scalar|null>> terug; waarden worden in PDO- en mysqli-adapters genormaliseerd naar dezelfde vorm van tekenreeks of null.


Snapshotter

Merql\Snapshot\Snapshotter legt de databasestatus vast. In tegenstelling tot de facade geeft deze u volledige controle over filters en slaat hij niets automatisch op.

__construct(DatabaseConnection $connection, ?Driver $driver = null, ?IdentityRuleSet $identityRules = null)

Als de driver niet is opgegeven, wordt deze automatisch gedetecteerd op basis van de verbindingsidentiteit. Geef een IdentityRuleSet mee als de rij-identiteit per tabel de schemastandaarden moet overschrijven.

capture(string $name, array $tables = [], array $filters = []): Snapshot

Leg de huidige status vast. Geef tabelnamen mee om het bereik te beperken. Geef filterobjecten mee om tabellen, kolommen of rijen uit te sluiten.

PHP
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

Leg fysieke tabellen vast onder canonieke tabelnamen. Gebruik dit wanneer dezelfde logische tabel in verschillende omgevingen andere fysieke namen heeft.

PHP
$snapshot = $snapshotter->captureAliased('sandbox', [
    'wp_onumia_abcd_posts' => 'wp_posts',
    'wp_onumia_abcd_postmeta' => 'wp_postmeta',
]);

De resulterende snapshot slaat canonieke tabelnamen op en behoudt tegelijk het fysieke tabelschema, de geconfigureerde identiteitskolommen, rijsleutels en filters.

fromData(string $name, array $tableData): Snapshot (statisch)

Bouw een snapshot op basis van ruwe gegevens zonder databaseverbinding. Handig voor tests of bij het importeren van gegevens uit een andere bron.

PHP
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 is een alleen-lezen waardeobject dat een volledige databasestatus vertegenwoordigt.

PHP
$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 bevat de rijen, fingerprints en het schema van één tabel.

PHP
$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 is invoergegevens voor Snapshotter::fromData().

PHP
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 definieert de kolommen waarmee rijsleutels worden opgebouwd.

PHP
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 (statisch)

Bepaal de standaardidentiteitsregel op basis van het schema: primaire sleutel, eerste unieke sleutel, daarna terugval op inhoud.

toArray(): array

Serialiseer de regel als ['type' => string, 'columns' => list<string>].

fromArray(array $data): IdentityRule (statisch)

Herstel een regel vanuit geserialiseerde gegevens.


IdentityRuleSet

Merql\Identity\IdentityRuleSet slaat identiteitsoverschrijvingen per tabel op.

PHP
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

Geeft een nieuwe regelset terug met een toegevoegde tabeloverschrijving.

conflictsFor(string $table, IdentityRule $rule, array $rows): array

Geef IdentityConflict-items terug als meerdere rijen voor een regel dezelfde sleutel opleveren.

toArray(): array

Serialiseer tabelregels als een JSON-veilige array.

fromArray(array $data): IdentityRuleSet (statisch)

Herstel een regelset vanuit geserialiseerde gegevens.


SnapshotStore

Merql\Snapshot\SnapshotStore slaat snapshots op en laadt ze als JSON-bestanden.

setDirectory(string $directory): void

Stel de opslagmap in. De standaard is .merql/snapshots.

save(Snapshot $snapshot): void

Schrijf een snapshot naar schijf.

load(string $name): Snapshot

Laad een snapshot op naam. Geeft SnapshotException als deze niet is gevonden.

exists(string $name): bool

Controleer of een snapshotbestand bestaat.

delete(string $name): void

Verwijder een snapshotbestand.


Differ

Merql\Diff\Differ vergelijkt twee snapshots en maakt een wijzigingsset.

diff(Snapshot $base, Snapshot $current): Changeset

PHP
use Merql\Diff\Differ;

$differ = new Differ();
$changeset = $differ->diff($baseSnapshot, $currentSnapshot);

valuesEqual(mixed $a, mixed $b): bool (statisch)

Vergelijk twee waarden door ze naar tekenreeksen om te zetten. NULL wordt als een afzonderlijke waarde behandeld: NULL === NULL is waar, NULL === '' is onwaar.


Wijzigingsset

Merql\Diff\Changeset is een alleen-lezen verzameling bewerkingen op rijniveau.

PHP
$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

Alleen-lezen waardeobjecten die afzonderlijke rijwijzigingen vertegenwoordigen.

RowInsert

PHP
$insert->table;                    // string
$insert->rowKey;                   // string
$insert->values;                   // array<string, mixed>

RowUpdate

PHP
$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

PHP
$delete->table;                    // string
$delete->rowKey;                   // string
$delete->oldValues;                // array<string, mixed>: values before deletion

ColumnDiff

Merql\Diff\ColumnDiff vertegenwoordigt één kolomwijziging binnen een rij-update.

PHP
$diff->column;                     // string
$diff->oldValue;                   // mixed
$diff->newValue;                   // mixed

ThreeWayMerge

Merql\Merge\ThreeWayMerge is het kernalgoritme voor samenvoegen.

__construct(?CellMergeConfig $cellMergeConfig = null)

Geef een CellMergeConfig mee om samenvoegen op celniveau in te schakelen voor TEXT- en JSON-kolommen.

PHP
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

Voer een three-way merge uit. Berekent intern wijzigingssets (van basis naar ours en van basis naar theirs) en voegt deze samen.

PHP
$result = $merge->merge($baseSnapshot, $oursSnapshot, $theirsSnapshot);

patch(Snapshot $base, Snapshot $changes): MergeResult

Snelkoppeling voor two-way merge. Gelijk aan merge($base, $base, $changes).

schemaMismatches(): array

Geeft SchemaException[] terug voor schemawijzigingen die tijdens de laatste merge zijn gevonden (kolommen die tussen snapshots zijn toegevoegd of verwijderd).


MergeResult

Merql\Merge\MergeResult is een alleen-lezen waardeobject met de uitkomst van de merge.

PHP
$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 is een serialiseerbaar reviewmodel voor een merge.

PHP
$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>

Gebruik MergePlanSerializer::toJson() en ::fromJson() voor stabiele JSON-roundtrips.

Selecties

ChangeGroupSelection slaat gefaseerde wijzigingsgroep-ID's op. Zet deze om in een OperationSelection bij het bouwen van geselecteerde mergeresultaten of terugdraaiplannen.

PHP
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 slaat inverse bewerkingen en verwachtingen voor afwijkingen op voor een geselecteerde toepassing.

PHP
use Merql\Rollback\RollbackPlanBuilder;
use Merql\Rollback\RollbackPlanSerializer;

$rollback = (new RollbackPlanBuilder())->build(
    'rollback-1',
    $plan,
    $operationSelection,
    $liveBeforeRows,
);

$json = RollbackPlanSerializer::toJson($rollback);

Gebruik RollbackDrift voordat u een terugdraaiing toepast en vervolgens RollbackPlanApplier om de inverse bewerkingen uit te voeren.


MergeOperation

Merql\Merge\MergeOperation is één opgeloste bewerking uit de merge.

PHP
$op->type;                         // string: 'insert' | 'update' | 'delete'
$op->table;                        // string
$op->rowKey;                       // string
$op->values;                       // array<string, mixed>
$op->source;                       // string: 'ours' | 'theirs' | 'merged'

Typeconstanten:

PHP
MergeOperation::TYPE_INSERT;       // 'insert'
MergeOperation::TYPE_UPDATE;       // 'update'
MergeOperation::TYPE_DELETE;       // 'delete'

Conflict

Merql\Merge\Conflict vertegenwoordigt een onopgelost mergeconflict.

PHP
$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

Conflicttypen

Type Betekenis
update_update Beide zijden hebben dezelfde kolom gewijzigd in verschillende waarden
update_delete Ours heeft een rij bijgewerkt die door theirs is verwijderd
delete_update Ours heeft een rij verwijderd die door theirs is bijgewerkt
insert_insert Beide zijden hebben een rij ingevoegd met dezelfde primaire sleutel

ConflictResolver

Merql\Merge\ConflictResolver past een oplossingsbeleid toe op alle conflicten in een mergeresultaat.

resolve(MergeResult $result, ConflictPolicy $policy): MergeResult (statisch)

Geeft een nieuwe MergeResult terug waarin conflicten volgens het beleid zijn opgelost.

PHP
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 is een backed enum met drie gevallen.

PHP
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 voert merge-logica per kolom uit voor één rij. Wordt intern gebruikt door ThreeWayMerge.

merge(string $table, string $rowKey, array $base, array $ours, array $theirs, ?CellMergeConfig $cellMergeConfig = null, array $columnTypes = []): array (statisch)

Geeft ['values' => array, 'conflicts' => list<Conflict>] terug.

PHP
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)

Applier

Merql\Apply\Applier voert een mergeresultaat uit op een database.

__construct(DatabaseConnection $connection, ?Driver $driver = null)

apply(MergeResult $result, ?Snapshot $base = null): ApplyResult

Voert alle bewerkingen uit in één transactie. Maakt de transactie bij elke fout ongedaan en rapporteert de fout in ApplyResult::errors() in plaats van deze op te werpen. Geeft ConflictException als het resultaat onopgeloste conflicten bevat.

PHP
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());
}

De volgorde op basis van foreign keys wordt automatisch afgehandeld: invoegingen worden gesorteerd op afhankelijkheden en verwijderingen in omgekeerde volgorde van afhankelijkheden.


ApplyResult

Merql\Apply\ApplyResult is een alleen-lezen waardeobject dat door de applier wordt teruggegeven.

PHP
$applied->rowsAffected();         // int
$applied->errors();               // list<string>
$applied->hasErrors();            // bool

Na een teruggedraaide toepassing telt rowsAffected() nog steeds de instructies die vóór de fout zijn uitgevoerd (#4). Controleer hasErrors() voordat u op het aantal vertrouwt.


DryRun

Merql\Apply\DryRun genereert leesbare SQL zonder iets uit te voeren.

generate(MergeResult $result, ?Snapshot $base = null, array $fkDependencies = [], ?Driver $driver = null): array (statisch)

Geeft een lijst met tekenreeksen van SQL terug, met ingesloten waarden (alleen voor weergave).

PHP
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 genereert geparametriseerde SQL-instructies. Wordt intern gebruikt door zowel Applier als DryRun.

generate(MergeResult $result, ?Snapshot $base = null, array $fkDependencies = [], ?Driver $driver = null): array (statisch)

Geeft list<array{sql: string, params: list<scalar|null>}> terug.

PHP
use Merql\Apply\SqlGenerator;

$statements = SqlGenerator::generate($result);

foreach ($statements as $stmt) {
    $connection->execute($stmt['sql'], $stmt['params']);
}

CellMergeConfig

Merql\CellMerge\CellMergeConfig configureert samenvoegstrategieën op celniveau voor specifieke kolommen of kolomtypen.

auto(): self (statisch)

Handige factory die TextCellMerger toewijst aan TEXT/LONGTEXT-kolommen en JsonCellMerger aan JSON-kolommen.

PHP
use Merql\CellMerge\CellMergeConfig;

$config = CellMergeConfig::auto();

forColumn(string $column, CellMerger $merger): self

Wijs een merger toe aan een specifieke kolom. Gebruik table.column voor gekwalificeerde namen of alleen column voor alle tabellen.

PHP
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

Wijs een merger toe aan alle kolommen die overeenkomen met een typepatroon (niet-hoofdlettergevoelige overeenkomst op basis van een substring).

PHP
use Merql\CellMerge\CellMergeConfig;
use Merql\CellMerge\JsonCellMerger;

$config = (new CellMergeConfig())
    ->forType('json', new JsonCellMerger());

getMerger(string $table, string $column, string $columnType = ''): CellMerger

Zoek de merger op voor een tabel, kolom en type. Prioriteit: gekwalificeerde kolomnaam, niet-gekwalificeerde kolomnaam, typepatroon, standaard (ondoorzichtig).


CellMerger (interface)

Merql\CellMerge\CellMerger is de interface voor samenvoegstrategieën op celniveau.

PHP
use Merql\CellMerge\CellMerger;
use Merql\CellMerge\CellMergeResult;

interface CellMerger
{
    public function merge(mixed $base, mixed $ours, mixed $theirs): CellMergeResult;
}

Er zijn drie ingebouwde implementaties beschikbaar.

TextCellMerger

Merql\CellMerge\TextCellMerger voegt tekst over meerdere regels samen met een driewegvergelijking per regel (hetzelfde algoritme dat git gebruikt voor bestandsinhoud). Als beide kanten verschillende regels bewerken, verloopt het samenvoegen probleemloos. Als beide kanten dezelfde regel op verschillende manieren bewerken, wordt een conflict gemeld.

PHP
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 voegt JSON-waarden samen door de hoofdsleutels afzonderlijk te vergelijken. Elke sleutel wordt samengevoegd met three-way-logica. Geneste objecten worden als ondoorzichtige JSON-tekenreeksen vergeleken (ze worden niet recursief samengevoegd).

PHP
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 is de standaard. Deze behandelt waarden als ondoorzichtige tekenreeksen en meldt altijd een conflict als ze verschillen.


CellMergeResult

Merql\CellMerge\CellMergeResult is het retourtype van alle celmergers.

PHP
$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 is een alleen-lezen weergave van de tabelstructuur.

PHP
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>

Driversysteem

merql gebruikt een uitbreidbaar driversysteem om databasespecifieke bewerkingen te abstraheren. Drivers worden automatisch gedetecteerd op basis van de driveridentiteit van de verbinding.

Driver (interface)

Merql\Driver\Driver definieert het contract dat alle databasestuurprogramma's implementeren.

PHP
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;
}

Ingebouwde implementaties: MysqlDriver en SqliteDriver.

DriverFactory

Merql\Driver\DriverFactory detecteert de driver automatisch op basis van een verbinding.

PHP
use Merql\Driver\DriverFactory;

$driver = DriverFactory::create($connection);

Registreer een aangepaste driver voor andere databases:

PHP
DriverFactory::register('pgsql', MyPostgresDriver::class);

Filters

TableFilter

Merql\Filter\TableFilter voegt tabellen toe of sluit ze uit met glob-patronen.

PHP
use Merql\Filter\TableFilter;

$filter = TableFilter::exclude(['cache_*', 'sessions', 'temp_*']);
$filter = TableFilter::include(['posts', 'users', 'comments']);

ColumnFilter

Merql\Filter\ColumnFilter verwijdert specifieke kolommen uit snapshots.

PHP
use Merql\Filter\ColumnFilter;

$filter = ColumnFilter::ignore(['updated_at', 'created_at', 'modified_date']);

RowFilter

Merql\Filter\RowFilter filtert rijen met een predicaatfunctie.

PHP
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;
});

Uitzonderingen

SnapshotException

Merql\Exceptions\SnapshotException wordt opgegooid wanneer een snapshot niet kan worden gevonden of een ongeldige naam heeft.

PHP
SnapshotException::notFound('baseline', '/path/to/baseline.json');

MergeException

Merql\Exceptions\MergeException wordt opgegooid wanneer voor een merge een vereiste snapshot ontbreekt.

PHP
MergeException::snapshotRequired('base');

ConflictException

Merql\Exceptions\ConflictException wordt opgegooid wanneer een mergeresultaat met onopgeloste conflicten wordt toegepast.

PHP
ConflictException::unresolved(3);
// Message: "Cannot apply merge with 3 unresolved conflict(s)"

SchemaException

Merql\Exceptions\SchemaException wordt opgegooid (of verzameld) wanneer schema's tussen snapshots verschillen.

PHP
SchemaException::mismatch('posts', 'column "tags" exists in current but not in base');

Schemamismatches stoppen de merge niet. Ze worden verzameld en zijn beschikbaar via $result->schemaMismatches() ter inspectie.