Справка за PHP API
Пълна справка за всички публични класове и методи в merql.
Merql (фасаден интерфейс)
Merql\Merql е статичната входна точка за често срещани операции. Тя обгръща класовете от по-ниско ниво и автоматично управлява съхраняването на моментни снимки.
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
Заснемете текущото състояние на базата данни и го запишете на диск. Подайте масив с имена на таблици, за да направите моментни снимки само на определени таблици, или не подавайте аргумент, за да включите всички таблици.
$snapshot = Merql::snapshot('baseline');
$snapshot = Merql::snapshot('baseline', ['posts', 'users']);
diff(string $base, string $current): Changeset
Заредете две именувани моментни снимки и изчислете набора от промени между тях. Не е необходим init(), тъй като се работи със съхранени моментни снимки.
$changeset = Merql::diff('before', 'after');
merge(string $base, string $ours, string $theirs): MergeResult
Сливане в три посоки на три именувани моментни снимки. Връща резултат с операции без конфликти и евентуални конфликти. Слива на ниво колона: фасадният интерфейс създава ThreeWayMerge без CellMergeConfig, затова не се прилага сливане на ниво клетка. За целта използвайте директно ThreeWayMerge.
$result = Merql::merge('base', 'ours', 'theirs');
patch(string $base, string $changes): MergeResult
Сливане в две посоки: прилагане на промените върху основата. Еквивалентно на merge($base, $base, $changes). Винаги създава резултат без конфликти, тъй като няма едновременни редакции. Работи само на ниво колона, както merge().
$result = Merql::patch('base', 'changes');
apply(MergeResult $result): ApplyResult
Изпълнете резултат от сливане без конфликти върху базата данни, подадена към init(). Необходим е init(). Извежда грешка ConflictException, ако останат неразрешени конфликти.
Изпълнява се всяка операция в резултата, затова пълният резултат от merge() се прилага без проблем само към база данни, която все още е в основното състояние. За база данни, в която вече е приложена едната страна, приложете избраните операции, които липсват там; вижте Защитено прилагане.
$applied = Merql::apply($result);
echo $applied->rowsAffected();
plan(string $id, string $base, string $ours, string $theirs, array $metadata = []): MergePlan
Изградете готов за UI план за сливане от три именувани моментни снимки. Планът включва стабилни
идентификатори на операциите, идентификатори на групите промени, контекст на операциите, конфликти, несъответствия в схемата, обобщение, метаданни и хеш на плана. Сливането е на ниво колона, както при
merge(); подайте резултат със сливане на клетките към MergePlanBuilder::build() за
сливане на ниво клетка.
$plan = Merql::plan('plan-1', 'base', 'ours', 'theirs', [
'source' => 'review-ui',
]);
applyGuarded(MergeResult $result, Snapshot $expectedLive): ApplyResult
Приложете резултат от сливане без конфликти с оптимистични предварителни условия за редовете в текущата база. За обновяване и изтриване е необходимо текущите редове да съвпадат с $expectedLive; при вмъкване идентичността не трябва вече да съществува в целевата база. $expectedLive е моментна снимка на целевата база данни (тяхната версия, когато прехвърляте нашата към базата, от която е направена тяхната моментна снимка). Всеки оператор, който не засяга нито един ред, води до връщане на транзакцията.
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
use Merql\Connection;
$connection = Connection::mysql('127.0.0.1', 'my_app', 'root', 'secret');
mysqli(string $host, string $database, string $username, string $password = '', int $port = 3306, string $charset = 'utf8mb4'): MysqliDatabaseConnection
$connection = Connection::mysqli('127.0.0.1', 'my_app', 'root', 'secret');
sqlite(string $path = ':memory:'): PdoDatabaseConnection
Създава връзка SQLite. Автоматично активира външните ключове чрез PRAGMA foreign_keys = ON.
$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().
$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:
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
Заснемете текущото състояние. Подайте имената на таблиците, за да ограничите обхвата. Подайте обекти на филтри, за да изключите таблици, колони или редове.
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
Заснемете физическите таблици с канонични имена на таблици. Използвайте това, когато една и съща логическа таблица има различни физически имена в различни среди.
$snapshot = $snapshotter->captureAliased('sandbox', [
'wp_onumia_abcd_posts' => 'wp_posts',
'wp_onumia_abcd_postmeta' => 'wp_postmeta',
]);
Получената моментна снимка съхранява каноничните имена на таблиците, като запазва схемата на физическите таблици, зададените колони за идентичност, ключовете на редовете и филтрите.
fromData(string $name, array $tableData): Snapshot (статичен)
Изградете моментна снимка от необработени данни без връзка към база данни. Полезно за тестване или при импортиране на данни от друг източник.
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 е обект-стойност само за четене, който представлява пълно състояние на база данни.
$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 съдържа редовете, отпечатъците и схемата на една таблица.
$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().
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 задава колоните, използвани за изграждане на ключове за редове.
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 съхранява специфични за таблицата замествания на идентичността.
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
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 е колекция само за четене от операции на ниво ред.
$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
$insert->table; // string
$insert->rowKey; // string
$insert->values; // array<string, mixed>
RowUpdate
$update->table; // string
$update->rowKey; // string
$update->columnDiffs; // list<ColumnDiff>
$update->fullRow; // array<string, mixed>: complete current row
$update->columnDiffMap(); // array<string, ColumnDiff>: keyed by column name
RowDelete
$delete->table; // string
$delete->rowKey; // string
$delete->oldValues; // array<string, mixed>: values before deletion
ColumnDiff
Merql\Diff\ColumnDiff представя една промяна в колона при актуализиране на ред.
$diff->column; // string
$diff->oldValue; // mixed
$diff->newValue; // mixed
ThreeWayMerge
Merql\Merge\ThreeWayMerge е основният алгоритъм за сливане.
__construct(?CellMergeConfig $cellMergeConfig = null)
Подайте CellMergeConfig, за да активирате сливане на ниво клетка за колони TEXT и JSON.
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
Извършва тристранно сливане. Изчислява вътрешно наборите от промени (от основата към нашата версия и от основата към тяхната) и ги слива.
$result = $merge->merge($baseSnapshot, $oursSnapshot, $theirsSnapshot);
patch(Snapshot $base, Snapshot $changes): MergeResult
Съкратен вариант за двустранно сливане. Еквивалентно на merge($base, $base, $changes).
schemaMismatches(): array
Връща SchemaException[] за всички открити разлики в схемата (добавени или премахнати колони между моментните снимки) при последното сливане.
MergeResult
Merql\Merge\MergeResult е обект със стойност, достъпна само за четене, който съдържа резултата от сливането.
$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 е сериализируем модел за преглед на сливане.
$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, когато създавате избрани резултати от сливане или планове за връщане назад.
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 съхранява обратни операции и очаквания за отклонение
при избрано прилагане.
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 е една разрешена операция от сливането.
$op->type; // string: 'insert' | 'update' | 'delete'
$op->table; // string
$op->rowKey; // string
$op->values; // array<string, mixed>
$op->source; // string: 'ours' | 'theirs' | 'merged'
Константи за типове:
MergeOperation::TYPE_INSERT; // 'insert'
MergeOperation::TYPE_UPDATE; // 'update'
MergeOperation::TYPE_DELETE; // 'delete'
Конфликт
Merql\Merge\Conflict представя неразрешен конфликт при сливане.
$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 с разрешени конфликти според политиката.
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 с три варианта.
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>].
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, ако резултатът съдържа неразрешени конфликти.
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 е обект със стойност, достъпна само за четене, който прилагащият механизъм връща.
$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 с вградени стойности (само за визуализация).
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>}>.
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.
use Merql\CellMerge\CellMergeConfig;
$config = CellMergeConfig::auto();
forColumn(string $column, CellMerger $merger): self
Задава обединител за конкретна колона. Използвайте table.column за квалифицирани имена или само column за всички таблици.
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
Задава обединител за всички колони, съвпадащи с шаблон за тип (съвпадение по подниз без значение от малки и главни букви).
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 е интерфейсът за стратегии за сливане на ниво клетка.
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 използва за съдържание на файлове). Когато двете страни редактират различни редове, сливането минава без конфликт. Когато редактират един и същ ред по различен начин, се отчита конфликт.
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 (не се сливат рекурсивно).
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 е типът на връщаната стойност от всички обединители на клетки.
$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 е представяне на структурата на таблица, достъпно само за четене.
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 задава договора, който изпълняват всички драйвери за бази данни.
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 открива драйвера автоматично от връзка.
use Merql\Driver\DriverFactory;
$driver = DriverFactory::create($connection);
Регистрирайте персонализиран драйвер за други бази данни:
DriverFactory::register('pgsql', MyPostgresDriver::class);
Филтри
TableFilter
Merql\Filter\TableFilter включва или изключва таблици чрез glob шаблони.
use Merql\Filter\TableFilter;
$filter = TableFilter::exclude(['cache_*', 'sessions', 'temp_*']);
$filter = TableFilter::include(['posts', 'users', 'comments']);
ColumnFilter
Merql\Filter\ColumnFilter премахва конкретни колони от моментните снимки.
use Merql\Filter\ColumnFilter;
$filter = ColumnFilter::ignore(['updated_at', 'created_at', 'modified_date']);
RowFilter
Merql\Filter\RowFilter филтрира редове чрез предикатна функция.
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 се хвърля, когато моментна снимка не може да бъде намерена или името ѝ е невалидно.
SnapshotException::notFound('baseline', '/path/to/baseline.json');
MergeException
Merql\Exceptions\MergeException се хвърля, когато липсва необходима моментна снимка за сливане.
MergeException::snapshotRequired('base');
ConflictException
Merql\Exceptions\ConflictException се хвърля при опит за прилагане на резултат от сливане с неразрешени конфликти.
ConflictException::unresolved(3);
// Message: "Cannot apply merge with 3 unresolved conflict(s)"
SchemaException
Merql\Exceptions\SchemaException се хвърля (или събира), когато схемите на моментните снимки се различават.
SchemaException::mismatch('posts', 'column "tags" exists in current but not in base');
Несъответствията в схемата не спират сливането. Те се събират и могат да бъдат прегледани чрез $result->schemaMismatches().