Sort array by parent_id and level

5 years ago

VojtaSim
Member | 55
+
0
-

Hi,
I have a problem with sorting array of ActiveRows. Since ActiveRow is read-only in Nette 2.1, multidimensional array is out of options. Only option left is flat array sorted by parent_id and level where every element with parent_id equal to NULL is followed by elements with parent_id set to it's ID and so on.
I tried some options using uasort but each of them worked olny for 2 level array and 3rd level elements were shifted to the end.

uasort($categoriesArray, function ($a, $b) {
    if ( $a['id'] == $b['id'] ) {
        return 0;

    } else if ( $a['parent_id'] ) {
        if ( $a['parent_id'] == $b['parent_id'] ) {
            return ( $a['id'] < $b['id'] ? -1 : 1 );
        } else {
            return ( $a['parent_id'] >= $b['id'] ? 1 : -1 );
        }
    } else if ( $b['parent_id'] ) {
        return ( $b['parent_id'] >= $a['id'] ? -1 : 1);
    } else {
        return ( $a['id'] < $b['id'] ? -1 : 1 );
    }
});

I also tried create some kind of wrapper (inspired here) for ActiveRow to break the read-only status, but I end up with 500 Internal Error.

Desired array:

array (7)
    0 => Nette\Database\Table\ActiveRow #1d0f
        . . .
        id => 1,
        parent_id => NULL,
        level => 1,
        name => ...
    1 => Nette\Database\Table\ActiveRow #337c
        . . .
        id => 2,
        parent_id => 1,
        level => 2,
        name => ...
    2 => Nette\Database\Table\ActiveRow #b63a
        . . .
        id => 3,
        parent_id => 1,
        level => 2,
        name => ...
    3 => Nette\Database\Table\ActiveRow #80c7
        . . .
        id => 4,
        parent_id => NULL,
        level => 1,
        name => ...
    4 => Nette\Database\Table\ActiveRow #2664
        . . .
        id => 5,
        parent_id => 4,
        level => 2,
        name => ...
    5 => Nette\Database\Table\ActiveRow #8ec6
        . . .
        id => 6,
        parent_id => ,
        level => 3,
        name => ...

A few notes: array shouldn't be sorted by id

5 years ago

VojtaSim
Member | 55
+
0
-

Ok never mind, I figured it out myself

private function buildTree($items, $parentId = 0, &$result = array()){
    foreach ($items as $key => $value) {
        if ($value['parent_id'] == $parentId) {
            if ($value['title'] == 'Unsorted')  // Unsorted will be always on top
                array_unshift($result, $value);
            else
                array_push($result, $value);

            unset($items[$key]);

            $oldParent = $parentId;
            $parentId = $value['id'];
            $this->buildTree($items, $parentId, $result);
            $parentId = $oldParent;
        }
    }
    return $result;
}