Към съдържанието

Справка за PHP API

Пълна справка за всички публични класове и методи в merql.

Merql (фасаден интерфейс)

Merql\Merql е статичната входна точка за често срещани операции. Тя обгръща класовете от по-ниско ниво и автоматично управлява съхраняването на моментни снимки.

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

Инициализирайте фасадния интерфейс с връзка към база данни. Трябва да извикате метода преди snapshot(), apply() или applyGuarded(); извикайте го отново, за да смените базите данни, например за да направите моментни снимки на нашата и тяхната версия от две различни копия. Без $driver се извиква DriverFactory::create(), който извежда грешка за механизми, различни от MySQL и SQLite, освен ако не е регистриран драйвер. Подайте драйвер, за да отмените автоматичното откриване, или набор от правила за идентичност, за да зададете идентичността на редовете за всяка таблица при заснемането на моментна снимка.

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

Заснемете текущото състояние на базата данни и го запишете на диск. Подайте масив с имена на таблици, за да направите моментни снимки само на определени таблици, или не подавайте аргумент, за да включите всички таблици.

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

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

Заредете две именувани моментни снимки и изчислете набора от промени между тях. Не е необходим init(), тъй като се работи със съхранени моментни снимки.

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

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

Сливане в три посоки на три именувани моментни снимки. Връща резултат с операции без конфликти и евентуални конфликти. Слива на ниво колона: фасадният интерфейс създава ThreeWayMerge без CellMergeConfig, затова не се прилага сливане на ниво клетка. За целта използвайте директно ThreeWayMerge.

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

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

Сливане в две посоки: прилагане на промените върху основата. Еквивалентно на merge($base, $base, $changes). Винаги създава резултат без конфликти, тъй като няма едновременни редакции. Работи само на ниво колона, както merge().

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

apply(MergeResult $result): ApplyResult

Изпълнете резултат от сливане без конфликти върху базата данни, подадена към init(). Необходим е init(). Извежда грешка ConflictException, ако останат неразрешени конфликти.

Изпълнява се всяка операция в резултата, затова пълният резултат от merge() се прилага без проблем само към база данни, която все още е в основното състояние. За база данни, в която вече е приложена едната страна, приложете избраните операции, които липсват там; вижте Защитено прилагане.

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

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

Изградете готов за UI план за сливане от три именувани моментни снимки. Планът включва стабилни идентификатори на операциите, идентификатори на групите промени, контекст на операциите, конфликти, несъответствия в схемата, обобщение, метаданни и хеш на плана. Сливането е на ниво колона, както при merge(); подайте резултат със сливане на клетките към MergePlanBuilder::build() за сливане на ниво клетка.

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

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

Приложете резултат от сливане без конфликти с оптимистични предварителни условия за редовете в текущата база. За обновяване и изтриване е необходимо текущите редове да съвпадат с $expectedLive; при вмъкване идентичността не трябва вече да съществува в целевата база. $expectedLive е моментна снимка на целевата база данни (тяхната версия, когато прехвърляте нашата към базата, от която е направена тяхната моментна снимка). Всеки оператор, който не засяга нито един ред, води до връщане на транзакцията.

PHP
use Merql\Snapshot\SnapshotStore;

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

reset(): void

Изчистете вътрешните екземпляри на връзката и Snapshotter. Използва се главно в тестове за нулиране на състоянието между изпълненията.


Връзка

Merql\Connection създава адаптери за връзки с подходящи настройки по подразбиране. При PDO връзките грешките се превръщат в изключения, режимът на извличане е асоциативен, емулираната подготовка е изключена, а извлечените стойности се преобразуват в низове. Адаптерът mysqli нормализира извлечените стойности до същия формат — низ или 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

Създава връзка SQLite. Автоматично активира външните ключове чрез PRAGMA foreign_keys = ON.

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

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

Свържете се чрез произволен PDO DSN низ. merql включва драйвери само за mysql и sqlite; други DSN отварят връзка, но Merql::init(), Snapshotter и инструментите за прилагане извеждат грешка Unsupported database driver, освен ако не е регистриран драйвер чрез DriverFactory::register().

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

fromPdo(PDO $pdo): PdoDatabaseConnection

Обвийте съществуващ екземпляр на PDO.

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

Обвийте съществуващ екземпляр на mysqli.

Договор за адаптерите

Всички адаптери реализират 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() и scalar() приемат позиционни параметри list<scalar|null> за плейсхолдъри ?. query() връща list<array<string, scalar|null>>; стойностите се нормализират до един и същ формат — низ или null — при PDO и mysqli адаптерите.


Създаване на моментна снимка

Merql\Snapshot\Snapshotter заснема състоянието на базата данни. За разлика от фасадния интерфейс, той ви дава пълен контрол върху филтрите и не съхранява данните автоматично.

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

Драйверът се открива автоматично по идентичността на връзката, ако не е зададен. Подайте IdentityRuleSet, когато идентичността на редовете за конкретна таблица трябва да замени настройките по подразбиране на схемата.

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

Заснемете текущото състояние. Подайте имената на таблиците, за да ограничите обхвата. Подайте обекти на филтри, за да изключите таблици, колони или редове.

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

Заснемете физическите таблици с канонични имена на таблици. Използвайте това, когато една и съща логическа таблица има различни физически имена в различни среди.

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

Получената моментна снимка съхранява каноничните имена на таблиците, като запазва схемата на физическите таблици, зададените колони за идентичност, ключовете на редовете и филтрите.

fromData(string $name, array $tableData): Snapshot (статичен)

Изградете моментна снимка от необработени данни без връзка към база данни. Полезно за тестване или при импортиране на данни от друг източник.

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

Моментна снимка

Merql\Snapshot\Snapshot е обект-стойност само за четене, който представлява пълно състояние на база данни.

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 съдържа редовете, отпечатъците и схемата на една таблица.

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 е входни данни за 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 задава колоните, използвани за изграждане на ключове за редове.

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 (статичен)

Извежда правилото за идентичност по подразбиране от схемата: първичен ключ, първи уникален ключ, след това резервен вариант със съдържанието.

toArray(): array

Сериализира правилото като ['type' => string, 'columns' => list<string>].

fromArray(array $data): IdentityRule (статичен)

Възстановява правило от сериализирани данни.


IdentityRuleSet

Merql\Identity\IdentityRuleSet съхранява специфични за таблицата замествания на идентичността.

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

Връща нов набор от правила с добавено заместване за една таблица.

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

Връща записите в IdentityConflict, когато няколко реда генерират един и същ ключ за дадено правило.

toArray(): array

Сериализира правилата за таблици като масив, безопасен за JSON.

fromArray(array $data): IdentityRuleSet (статичен)

Възстановява набор от правила от сериализирани данни.


SnapshotStore

Merql\Snapshot\SnapshotStore съхранява и зарежда моментни снимки като файлове JSON.

setDirectory(string $directory): void

Задава директорията за съхранение. По подразбиране е .merql/snapshots.

save(Snapshot $snapshot): void

Записва моментна снимка на диска.

load(string $name): Snapshot

Зарежда моментна снимка по име. Хвърля SnapshotException, ако не бъде намерена.

exists(string $name): bool

Проверява дали файлът на моментната снимка съществува.

delete(string $name): void

Премахва файла на моментната снимка.


Сравнител

Merql\Diff\Differ сравнява две моментни снимки и генерира набор от промени.

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 (статичен)

Сравнява две стойности, като ги преобразува в низове. NULL се третира като отделна стойност: NULL === NULL е истина, NULL === '' е лъжа.


Набор от промени

Merql\Diff\Changeset е колекция само за четене от операции на ниво ред.

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

Обекти със стойност, достъпна само за четене, които представят отделни промени по редове.

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 представя една промяна в колона при актуализиране на ред.

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

ThreeWayMerge

Merql\Merge\ThreeWayMerge е основният алгоритъм за сливане.

__construct(?CellMergeConfig $cellMergeConfig = null)

Подайте CellMergeConfig, за да активирате сливане на ниво клетка за колони TEXT и 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

Извършва тристранно сливане. Изчислява вътрешно наборите от промени (от основата към нашата версия и от основата към тяхната) и ги слива.

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

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

Съкратен вариант за двустранно сливане. Еквивалентно на merge($base, $base, $changes).

schemaMismatches(): array

Връща SchemaException[] за всички открити разлики в схемата (добавени или премахнати колони между моментните снимки) при последното сливане.


MergeResult

Merql\Merge\MergeResult е обект със стойност, достъпна само за четене, който съдържа резултата от сливането.

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 е сериализируем модел за преглед на сливане.

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>

Използвайте MergePlanSerializer::toJson() и ::fromJson() за стабилни двупосочни преобразувания JSON.

Избори

ChangeGroupSelection съхранява идентификаторите на етапираните групи промени. Преобразувайте го в OperationSelection, когато създавате избрани резултати от сливане или планове за връщане назад.

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 съхранява обратни операции и очаквания за отклонение при избрано прилагане.

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

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

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

Използвайте RollbackDrift преди прилагане на връщане назад, след което RollbackPlanApplier, за да изпълните обратните операции.


MergeOperation

Merql\Merge\MergeOperation е една разрешена операция от сливането.

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

Константи за типове:

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

Конфликт

Merql\Merge\Conflict представя неразрешен конфликт при сливане.

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

Типове конфликти

Тип Значение
update_update Двете страни са променили една и съща колона с различни стойности
update_delete Нашата страна е актуализирала ред, който тяхната е изтрила
delete_update Нашата страна е изтрила ред, който тяхната е актуализирала
insert_insert Двете страни са вмъкнали ред със същия първичен ключ

ConflictResolver

Merql\Merge\ConflictResolver прилага политика за разрешаване на всички конфликти в резултат от сливане.

resolve(MergeResult $result, ConflictPolicy $policy): MergeResult (статичен)

Връща нов MergeResult с разрешени конфликти според политиката.

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 е enum с три варианта.

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 изпълнява логика за сливане по колони за един ред. Използва се вътрешно от ThreeWayMerge.

merge(string $table, string $rowKey, array $base, array $ours, array $theirs, ?CellMergeConfig $cellMergeConfig = null, array $columnTypes = []): array (статичен)

Връща ['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)

Прилагащ механизъм

Merql\Apply\Applier изпълнява резултат от сливане спрямо база данни.

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

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

Изпълнява всички операции в рамките на една транзакция. При грешка отменя транзакцията и я отчита в ApplyResult::errors(), вместо да хвърли изключение. Хвърля ConflictException, ако резултатът съдържа неразрешени конфликти.

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

Подреждането по външни ключове се обработва автоматично: вмъкванията се сортират по реда на зависимостите, а изтриванията — в обратен ред.


ApplyResult

Merql\Apply\ApplyResult е обект със стойност, достъпна само за четене, който прилагащият механизъм връща.

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

След отменено прилагане rowsAffected() все още отчита заявките, изпълнени преди грешката (#4). Проверете hasErrors(), преди да се доверите на броя.


DryRun

Merql\Apply\DryRun генерира разбираеми за хората SQL, без да изпълнява нищо.

generate(MergeResult $result, ?Snapshot $base = null, array $fkDependencies = [], ?Driver $driver = null): array (статичен)

Връща списък от низове SQL с вградени стойности (само за визуализация).

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 генерира параметризирани заявки SQL. Използва се вътрешно както от Applier, така и от DryRun.

generate(MergeResult $result, ?Snapshot $base = null, array $fkDependencies = [], ?Driver $driver = null): array (статичен)

Връща 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 конфигурира стратегии за сливане на ниво клетка за конкретни колони или типове колони.

auto(): self (статичен)

Фабричен метод за удобство, който задава TextCellMerger за колони TEXT/LONGTEXT и JsonCellMerger за колони JSON.

PHP
use Merql\CellMerge\CellMergeConfig;

$config = CellMergeConfig::auto();

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

Задава обединител за конкретна колона. Използвайте table.column за квалифицирани имена или само column за всички таблици.

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

Задава обединител за всички колони, съвпадащи с шаблон за тип (съвпадение по подниз без значение от малки и главни букви).

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

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

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

Търси обединителя за дадена таблица, колона и тип. Приоритет: квалифицирано име на колона, неквалифицирано име на колона, шаблон за тип, по подразбиране (непрозрачен).


CellMerger (интерфейс)

Merql\CellMerge\CellMerger е интерфейсът за стратегии за сливане на ниво клетка.

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

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

Предоставени са три вградени реализации.

TextCellMerger

Merql\CellMerge\TextCellMerger слива многострочен текст чрез тристранно сравнение ред по ред (същият алгоритъм, който git използва за съдържание на файлове). Когато двете страни редактират различни редове, сливането минава без конфликт. Когато редактират един и същ ред по различен начин, се отчита конфликт.

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 слива стойности JSON, като сравнява ключовете от най-горно ниво поотделно. Всеки ключ се слива чрез тристранна логика. Вложените обекти се сравняват като непрозрачни низове JSON (не се сливат рекурсивно).

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 е вариантът по подразбиране. Третира стойностите като непрозрачни низове и винаги отчита конфликт, когато се различават.


CellMergeResult

Merql\CellMerge\CellMergeResult е типът на връщаната стойност от всички обединители на клетки.

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 е представяне на структурата на таблица, достъпно само за четене.

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>

Система от драйвери

merql използва разширяема система от драйвери, за да абстрахира специфичните за базата данни операции. Драйверите се откриват автоматично според идентификатора на драйвера на връзката.

Driver (интерфейс)

Merql\Driver\Driver задава договора, който изпълняват всички драйвери за бази данни.

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

Вградени реализации: MysqlDriver и SqliteDriver.

DriverFactory

Merql\Driver\DriverFactory открива драйвера автоматично от връзка.

PHP
use Merql\Driver\DriverFactory;

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

Регистрирайте персонализиран драйвер за други бази данни:

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

Филтри

TableFilter

Merql\Filter\TableFilter включва или изключва таблици чрез glob шаблони.

PHP
use Merql\Filter\TableFilter;

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

ColumnFilter

Merql\Filter\ColumnFilter премахва конкретни колони от моментните снимки.

PHP
use Merql\Filter\ColumnFilter;

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

RowFilter

Merql\Filter\RowFilter филтрира редове чрез предикатна функция.

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

Изключения

SnapshotException

Merql\Exceptions\SnapshotException се хвърля, когато моментна снимка не може да бъде намерена или името ѝ е невалидно.

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

MergeException

Merql\Exceptions\MergeException се хвърля, когато липсва необходима моментна снимка за сливане.

PHP
MergeException::snapshotRequired('base');

ConflictException

Merql\Exceptions\ConflictException се хвърля при опит за прилагане на резултат от сливане с неразрешени конфликти.

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

SchemaException

Merql\Exceptions\SchemaException се хвърля (или събира), когато схемите на моментните снимки се различават.

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

Несъответствията в схемата не спират сливането. Те се събират и могат да бъдат прегледани чрез $result->schemaMismatches().