Treci la conținut

Referință PHP API

Referință completă pentru toate clasele și metodele publice din merql.

Merql (fațadă)

Merql\Merql este punctul de intrare static pentru operațiile uzuale. Încapsulează clasele de nivel inferior și gestionează automat persistența instantaneelor.

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

Inițializați fațada cu o conexiune la baza de date. Trebuie apelată înainte de snapshot(), apply() sau applyGuarded(); apelați-o din nou pentru a schimba baza de date, de exemplu pentru a crea instantanee pentru partea noastră și partea lor din două copii diferite. În lipsa unui $driver, apelează DriverFactory::create(), care generează o excepție pentru alte motoare decât MySQL și SQLite, dacă nu este înregistrat un driver. Transmiteți un driver pentru a înlocui detectarea automată sau un set de reguli de identitate pentru a înlocui identitatea rândurilor per tabel în timpul capturării instantaneului.

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

Capturați starea curentă a bazei de date și salvați-o pe disc. Transmiteți un tablou cu numele tabelelor pentru a crea instantanee doar pentru anumite tabele sau omiteți-l pentru toate tabelele.

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

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

Încărcați două instantanee cu nume și calculați setul de modificări dintre ele. Nu necesită init(), deoarece folosește instantanee persistate.

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

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

Îmbinare în trei direcții a trei instantanee cu nume. Returnează un rezultat care conține operații fără conflicte și eventuale conflicte. Îmbină la nivel de coloană: fațada construiește ThreeWayMerge fără un CellMergeConfig, deci îmbinarea la nivel de celulă nu se aplică. Pentru aceasta, folosiți direct ThreeWayMerge.

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

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

Îmbinare în două direcții: aplică modificările peste baza inițială. Echivalentă cu merge($base, $base, $changes). Produce întotdeauna un rezultat fără conflicte, deoarece nu există editări concurente. Doar la nivel de coloană, la fel ca merge().

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

apply(MergeResult $result): ApplyResult

Execută un rezultat de îmbinare fără conflicte asupra bazei de date transmise către init(). Necesită init(). Generează ConflictException dacă rămân conflicte nerezolvate.

Fiecare operație din rezultat este executată, așa că rezultatul complet al merge() se aplică fără probleme doar unei baze de date care încă păstrează starea inițială. Pentru o bază de date care conține deja una dintre părți, aplicați operațiile care îi lipsesc; consultați Aplicare cu verificări.

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

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

Construiți un plan de îmbinare compatibil cu UI din trei instantanee cu nume. Planul include ID-uri stabile ale operațiilor, ID-uri ale grupurilor de modificări, contextul operațiilor, conflicte, nepotriviri de schemă, un rezumat, metadate și un hash al planului. Îmbinarea este la nivel de coloană, ca în merge(); transmiteți un rezultat îmbinat la nivel de celulă către MergePlanBuilder::build() pentru îmbinarea la nivel de celulă.

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

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

Aplicați un rezultat de îmbinare fără conflicte, cu precondiții optimiste pentru rândurile curente. Actualizările și ștergerile necesită ca rândurile curente să corespundă cu $expectedLive; inserările necesită ca identitatea țintă să nu existe deja. $expectedLive este un instantaneu al bazei de date țintă (partea lor, când promovați partea noastră în baza de date din care a fost capturată partea lor). Orice instrucțiune care afectează zero rânduri anulează tranzacția.

PHP
use Merql\Snapshot\SnapshotStore;

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

reset(): void

Șterge instanțele interne de conexiune și Snapshotter. Folosit în principal în teste pentru a reseta starea între rulări.


Conexiune

Merql\Connection construiește adaptoare de conexiune cu valori implicite adecvate. Conexiunile PDO folosesc excepții la erori, modul de extragere asociativă, fără pregătiri simulate și valori extrase convertite în șiruri. Adaptorul mysqli normalizează valorile extrase la aceeași formă șir sau 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

Creează o conexiune SQLite. Activează automat cheile externe prin PRAGMA foreign_keys = ON.

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

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

Conectați-vă folosind orice șir DSN PDO. merql include drivere doar pentru mysql și sqlite; celelalte DSN-uri deschid o conexiune, dar Merql::init(), Snapshotter și aplicatoarele generează Unsupported database driver, dacă nu este înregistrat un driver cu DriverFactory::register().

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

fromPdo(PDO $pdo): PdoDatabaseConnection

Încapsulează o instanță PDO existentă.

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

Încapsulează o instanță mysqli existentă.

Contractul adaptorului

Toate adaptoarele implementează 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() și scalar() acceptă parametri poziționali list<scalar|null> pentru substituenții ?. query() returnează list<array<string, scalar|null>>; valorile sunt normalizate la aceeași formă șir sau null în adaptoarele PDO și mysqli.


Snapshotter

Merql\Snapshot\Snapshotter capturează starea bazei de date. Spre deosebire de fațadă, vă oferă control deplin asupra filtrelor și nu salvează automat rezultatele.

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

Dacă nu este specificat, driverul este detectat automat pe baza identității conexiunii. Transmiteți un IdentityRuleSet când identitatea rândurilor specifică tabelului trebuie să înlocuiască valorile implicite ale schemei.

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

Capturați starea curentă. Transmiteți numele tabelelor pentru a limita aria. Transmiteți obiecte de filtrare pentru a exclude tabele, coloane sau rânduri.

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

Capturați tabelele fizice folosind numele canonice ale tabelelor. Folosiți această opțiune când același tabel logic are nume fizice diferite în medii diferite.

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

Instantaneul rezultat stochează numele canonice ale tabelelor, păstrând în același timp schema tabelului fizic, coloanele de identitate configurate, cheile rândurilor și filtrele.

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

Construiește un instantaneu din date brute fără conexiune la baza de date. Util pentru teste sau la importul datelor din altă sursă.

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']),
]);

Instantaneu

Merql\Snapshot\Snapshot este un obiect readonly care reprezintă o stare completă a bazei de date.

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 conține rândurile, amprentele și schema unui 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 reprezintă date de intrare pentru 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 definește coloanele folosite pentru a construi cheile rândurilor.

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 (static)

Rezolvă regula de identitate implicită din schemă: cheie primară, prima cheie unică, apoi la conținut.

toArray(): array

Serializează regula ca ['type' => string, 'columns' => list<string>].

fromArray(array $data): IdentityRule (static)

Încarcă o regulă din date serializate.


IdentityRuleSet

Merql\Identity\IdentityRuleSet stochează suprascrieri ale identității specifice tabelelor.

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

Returnează un set nou de reguli, cu o suprascriere adăugată pentru un tabel.

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

Returnează intrările IdentityConflict când mai multe rânduri produc aceeași cheie pentru o regulă.

toArray(): array

Serializează regulile tabelelor ca tablou sigur pentru JSON.

fromArray(array $data): IdentityRuleSet (static)

Încarcă un set de reguli din date serializate.


SnapshotStore

Merql\Snapshot\SnapshotStore salvează și încarcă instantanee ca fișiere JSON.

setDirectory(string $directory): void

Setează directorul de stocare. Valoarea implicită este .merql/snapshots.

save(Snapshot $snapshot): void

Scrie un instantaneu pe disc.

load(string $name): Snapshot

Încarcă un instantaneu după nume. Generează SnapshotException dacă nu este găsit.

exists(string $name): bool

Verifică dacă există un fișier de instantaneu.

delete(string $name): void

Elimină un fișier de instantaneu.


Comparator

Merql\Diff\Differ compară două instantanee și produce un set de modificări.

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 (static)

Compară două valori convertindu-le în șiruri. NULL este tratat ca valoare distinctă: NULL === NULL este adevărat, NULL === '' este fals.


Set de modificări

Merql\Diff\Changeset este o colecție readonly de operații la nivel de rând.

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

Obiecte readonly care reprezintă modificări individuale ale rândurilor.

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 reprezintă o singură modificare de coloană în cadrul unei actualizări de rând.

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

ThreeWayMerge

Merql\Merge\ThreeWayMerge este algoritmul central de îmbinare.

__construct(?CellMergeConfig $cellMergeConfig = null)

Transmiteți un CellMergeConfig pentru a activa îmbinarea la nivel de celulă pentru coloanele TEXT și JSON.

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

Efectuează o îmbinare în trei direcții. Calculează intern seturile de modificări (de la baza inițială la partea noastră și de la baza inițială la partea lor) și le îmbină.

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

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

Scurtătură pentru îmbinarea în două direcții. Echivalentă cu merge($base, $base, $changes).

schemaMismatches(): array

Returnează SchemaException[] pentru toate diferențele de schemă detectate în timpul ultimei îmbinări (coloane adăugate sau eliminate între instantanee).


MergeResult

Merql\Merge\MergeResult este un obiect readonly care conține rezultatul îmbinării.

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 este un model de revizuire serializabil pentru o îmbinare.

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>

Folosiți MergePlanSerializer::toJson() și ::fromJson() pentru parcurgeri dus-întors JSON stabile.

Selecții

ChangeGroupSelection stochează ID-urile grupurilor de modificări etapizate. Convertiți-l într-un OperationSelection la construirea rezultatelor de îmbinare selectate sau a planurilor de revenire.

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 stochează operațiile inverse și așteptările privind deriva pentru o aplicare selectată.

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

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

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

Folosiți RollbackDrift înainte de a aplica revenirea, apoi RollbackPlanApplier pentru a rula operațiile inverse.


MergeOperation

Merql\Merge\MergeOperation este o singură operație rezolvată din îmbinare.

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

Constante de tip:

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

Conflict

Merql\Merge\Conflict reprezintă un conflict de îmbinare nerezolvat.

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

Tipuri de conflicte

Tip Semnificație
update_update Ambele părți au modificat aceeași coloană cu valori diferite
update_delete Partea noastră a actualizat un rând pe care partea lor l-a șters
delete_update Partea noastră a șters un rând pe care partea lor l-a actualizat
insert_insert Ambele părți au inserat un rând cu aceeași cheie primară

ConflictResolver

Merql\Merge\ConflictResolver aplică o politică de rezolvare tuturor conflictelor dintr-un rezultat de îmbinare.

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

Returnează un nou MergeResult cu conflictele rezolvate conform politicii.

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 este un enum backed cu trei cazuri.

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 aplică logica de îmbinare per coloană pentru un singur rând. Este folosit intern de ThreeWayMerge.

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

Returnează ['values' => array, 'conflicts' => list<Conflict>].

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)

Aplicator

Merql\Apply\Applier execută un rezultat de îmbinare asupra unei baze de date.

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

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

Execută toate operațiile într-o singură tranzacție. Revine asupra tranzacției la orice eroare și o raportează în ApplyResult::errors() în loc să genereze o excepție. Generează ConflictException dacă rezultatul conține conflicte nerezolvate.

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

Ordinea cheilor externe este gestionată automat: inserările sunt sortate în ordinea dependențelor, iar ștergerile în ordinea inversă a dependențelor.


ApplyResult

Merql\Apply\ApplyResult este un obiect readonly returnat de aplicator.

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

După o aplicare anulată, rowsAffected() numără în continuare instrucțiunile executate înainte de eșec (#4). Verificați hasErrors() înainte de a vă baza pe număr.


DryRun

Merql\Apply\DryRun generează SQL lizibile de oameni fără să execute nimic.

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

Returnează o listă de șiruri SQL cu valorile incluse direct (doar în scopuri de afișare).

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 generează instrucțiuni SQL parametrizate. Folosit intern atât de Applier, cât și de DryRun.

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

Returnează list<array{sql: string, params: list<scalar|null>}>.

PHP
use Merql\Apply\SqlGenerator;

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

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

CellMergeConfig

Merql\CellMerge\CellMergeConfig configurează strategii de îmbinare la nivel de celulă pentru coloane sau tipuri de coloane specifice.

auto(): self (static)

Funcție utilitară care atribuie TextCellMerger coloanelor TEXT/LONGTEXT și JsonCellMerger coloanelor JSON.

PHP
use Merql\CellMerge\CellMergeConfig;

$config = CellMergeConfig::auto();

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

Atribuie un îmbinător unei coloane specifice. Folosiți table.column pentru nume calificate sau doar column pentru toate tabelele.

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

Atribuie un îmbinător tuturor coloanelor care corespund unui tipar de tip (potrivire insensibilă la majuscule și minuscule după subșir).

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

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

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

Caută îmbinătorul pentru un tabel, o coloană și un tip date. Prioritate: numele calificat al coloanei, numele necalificat al coloanei, tiparul de tip, valoarea implicită (opac).


CellMerger (interfață)

Merql\CellMerge\CellMerger este interfața strategiilor de îmbinare la nivel de celulă.

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

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

Sunt furnizate trei implementări încorporate.

TextCellMerger

Merql\CellMerge\TextCellMerger îmbină text pe mai multe rânduri folosind o comparație linie cu linie în trei direcții (același algoritm pe care git îl folosește pentru conținutul fișierelor). Când cele două părți modifică rânduri diferite, îmbinarea reușește fără conflicte. Când ambele modifică același rând în mod diferit, raportează un conflict.

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 îmbină valorile JSON comparând separat cheile de nivel superior. Fiecare cheie este îmbinată folosind logica în trei căi. Obiectele imbricate sunt comparate ca șiruri JSON opace (nu sunt îmbinate recursiv).

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 este opțiunea implicită. Tratează valorile ca șiruri opace și raportează întotdeauna un conflict atunci când diferă.


CellMergeResult

Merql\CellMerge\CellMergeResult este tipul de returnare pentru toate funcțiile de îmbinare a celulelor.

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 este o reprezentare doar pentru citire a structurii tabelului.

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>

Sistemul de drivere

merql folosește un sistem de drivere extensibil pentru a abstractiza operațiile specifice bazelor de date. Driverele sunt detectate automat pe baza identității driverului conexiunii.

Driver (interfață)

Merql\Driver\Driver definește contractul implementat de toate driverele de baze de date.

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

Implementări incluse: MysqlDriver și SqliteDriver.

DriverFactory

Merql\Driver\DriverFactory detectează automat driverul unei conexiuni.

PHP
use Merql\Driver\DriverFactory;

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

Înregistrați un driver personalizat pentru alte baze de date:

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

Filtre

TableFilter

Merql\Filter\TableFilter include sau exclude tabele folosind modele glob.

PHP
use Merql\Filter\TableFilter;

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

ColumnFilter

Merql\Filter\ColumnFilter elimină coloane specifice din instantanee.

PHP
use Merql\Filter\ColumnFilter;

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

RowFilter

Merql\Filter\RowFilter filtrează rândurile folosind o funcție predicat.

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

Excepții

SnapshotException

Merql\Exceptions\SnapshotException este aruncată când o instantanee nu poate fi găsită sau are un nume nevalid.

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

MergeException

Merql\Exceptions\MergeException este aruncată când lipsește o instantanee necesară pentru o îmbinare.

PHP
MergeException::snapshotRequired('base');

ConflictException

Merql\Exceptions\ConflictException este aruncată când se încearcă aplicarea unui rezultat de îmbinare cu conflicte nerezolvate.

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

SchemaException

Merql\Exceptions\SchemaException este aruncată (sau colectată) când schemele diferă între instantanee.

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

Nepotrivirile de schemă nu opresc îmbinarea. Acestea sunt colectate și pot fi inspectate prin $result->schemaMismatches().