I think you could use the uasort()
function for your needs.
To define your comparison function, I would suggest to transform all the after
conditions to the before
conditions:
$array = [
[
'id' => 14,
'parentId' => 0,
'before' => 15
],
[
'id' => 15,
'parentId' => 0,
'after' => 14
],
[
'id' => 9,
'parentId' => 0,
'after' => 15
],
[
'id' => 8,
'parentId' => 0,
'after' => 9
],
[
'id' => 1,
'parentId' => 0,
'after' => 14
]
];
//transform all after conditions to before conditions
function defineBeforeCondition($array)
{
$befores = array_column($array, 'before', 'id');
$afters = array_column($array, 'after', 'id');
return array_merge(array_chunk($befores, 1, true), array_map('array_flip', array_chunk($afters, 1, true)));
}
$condition = defineBeforeCondition($array);
Now you could use the $condition
in your comparison function:
$compare = function ($array1, $array2) use ($condition)
{
//iterate through before conditions
foreach ($condition as $before) {
//if there is a match
if (isset($before[$array1['id']]) && $before[$array1['id']] === $array2['id']) {
//if the value of the first element is greater than the value of the second element,
//but the first element should precede the second, return -1
if ($array1['id'] > $array2['id']) {
return -1;
}
//otherwise make a normal comparison
//note the spaceship operator for PHP >= 7.0
return $array1['id'] <=> $array2['id'];
}
}
//no data, move down the first element
return 1;
};
uasort($array, $compare);
var_dump($array);
array (size=5)
0 =>
array (size=3)
'id' => int 14
'parentId' => int 0
'before' => int 15
4 =>
array (size=3)
'id' => int 1
'parentId' => int 0
'after' => int 14
1 =>
array (size=3)
'id' => int 15
'parentId' => int 0
'after' => int 14
2 =>
array (size=3)
'id' => int 9
'parentId' => int 0
'after' => int 15
3 =>
array (size=3)
'id' => int 8
'parentId' => int 0
'after' => int 9