User docs →
README.md· Agent quick-ref →CLAUDE.md· Agent deep dive →AGENTS.md
Topological-sort helpers for declaring
before,after, anddependsrelationships between modules and pipeline items.
A thin layer on top of marcj/topsort that gives Flyokai a single, consistent way to order things — modules at bootstrap, ACL tuners, indexers, setup steps, anywhere a list needs to be deterministic.
sortComposition(array $items)— sorts items bybefore/after/dependsdeclarationscastCompositionArgument(array $items, string $name, string $key)— sort + validate, returns ordered class namesassertCompositionKeys()— ensures every item has the keys it mustmergeDepends()— merge & dedupe dependency arraysArraySortGroup— extendsMJS\TopSort\Implementations\ArraySortwith grouping for parallel-safe execution
composer require flyokai/compositionuse function Flyokai\Composition\sortComposition;
$items = [
'cache' => ['className' => Cache::class, 'after' => 'config'],
'config' => ['className' => Config::class],
'db' => ['className' => Db::class, 'depends' => 'config'],
'http' => ['className' => Http::class, 'before' => 'db'],
];
$sorted = sortComposition($items);
// Returns: ['http', 'config', 'cache', 'db'] — keys preserved, order corrected[
'itemName' => [
'className' => 'Full\\Class\\Name',
'before' => 'item2,item3', // string or array
'after' => 'item1', // string or array
'depends' => 'other1,other2', // string or array
]
]| Mechanism | Semantics |
|---|---|
before |
"this item comes before X" → X depends on this item |
after |
"this item comes after X" → this item depends on X |
depends |
direct dependency declaration |
before is intentionally inverted — 'before' => 'cache' means cache depends on the current item, not the other way.
use function Flyokai\Composition\castCompositionArgument;
$ordered = castCompositionArgument($items, 'modules', 'className');
// ['Http\\Class', 'Config\\Class', 'Cache\\Class', 'Db\\Class']assertCompositionKeys($items, ['className', 'tag'], 'pipelines') enforces that every entry contains the listed keys after sorting.
use Flyokai\Composition\TopSort\ArraySortGroup;
$sorter = new ArraySortGroup();
$sorter->add('a', []);
$sorter->add('b', ['a']);
$sorter->add('c', []);
$sorter->add('d', ['b']);
$sorter->sorted(); // ['a', 'c', 'b', 'd']
$sorter->grouped(); // [['a', 'c'], ['b'], ['d']] — items in a group are independentgrouped() returns dependency cohorts — every item in a cohort can run in parallel without violating ordering.
beforeis inverted.'before' => 'cache'declares cache as depending on this item.- Missing dependencies throw —
ElementNotFoundException. No silent omission. - Cycles throw —
CircularDependencyExceptionvia parent tracking. - Adding elements after sorting invalidates the cached result; a full re-sort runs on next access.
- Accepts
'a,b',['a','b'], or empty string interchangeably (empties are filtered out).
flyokai/applicationuses this for module ordering and DB setup steps.- amphp-injector ships its own
CompositionOrderedfor ordered DI compositions, built on the same primitives.
MIT