accordsync / core
Accord's merge core for PHP: hybrid logical clocks, operations, lww, counter, set and conflict.
Requires
- php: >=8.3
- ext-json: *
- ext-mbstring: *
Requires (Dev)
None
Suggests
None
Provides
None
Conflicts
None
Replaces
None
README
Accord's merge core for PHP: hybrid logical clocks, operations and the four merge strategies.
Pure PHP, no I/O. Most apps use accordsync/server
or its Laravel and Symfony packages, which depend on it. PHP 8.3+.
composer require accordsync/core
| Strategy | Merges by |
|---|---|
Schema::lww() |
Highest hybrid logical clock wins. |
Schema::counter() |
Sum of every increment; none is ever lost. |
Schema::set() |
Add-wins set: a remove only removes what its writer had seen. |
Schema::conflict() |
Concurrent values are all kept and the field is flagged; a resolution supersedes exactly the values its writer saw. |
use Accord\Core\{Json, LocalWriter, Schema}; $schema = Schema::define(['dossier' => ['visits' => Schema::counter(), 'status' => Schema::conflict()]]); $now = fn () => (int) (microtime(true) * 1000); $a = new LocalWriter($schema, 'phone-a', $now); $b = new LocalWriter($schema, 'phone-b', $now); // Each device writes offline... $fromA = [$a->inc('dossier:1', 'visits', 1), $a->assign('dossier:1', 'status', 'approved')]; $fromB = [$b->inc('dossier:1', 'visits', 2), $b->assign('dossier:1', 'status', 'rejected')]; // ...then they exchange ops, in any order, as often as the network repeats them. foreach ([...$fromB, ...$fromB] as $op) { $a->receive($op); } foreach (array_reverse($fromA) as $op) { $b->receive($op); } echo Json::canonical($a->replica()->read('dossier:1')); // {"status":{"conflicted":[{"opId":"phone-a:2","value":"approved"},{"opId":"phone-b:2","value":"rejected"}]},"visits":3} var_dump($a->replica()->snapshot() === $b->replica()->snapshot()); // bool(true)
Objects in values are Accord\Core\JsonObject (PHP arrays cannot tell {} from []), and
Json::canonical() writes the same canonical JSON as the TypeScript core.
It merges byte for byte like @accordsync/core:
the test suite runs the shared golden vectors in every delivery order, and random scenarios
generated by the TypeScript core must produce identical snapshots here.
Docs: accord.benhattab.pro/docs/schema · Source: crossben/accordsync-php · Licence: Apache-2.0