0

Hello I am think about how to build this array with a recursive function with a lot of layer. So the data would like that.

id belongs_to
1a  NULL
2a  NULL
3a  1a
4a  NULL
5a  2a

And non-recursive function like:

foreach ($first_layer as $first_layer_obj) {
        $array[$first_layer_obj->id] = [];
        $second_layer = /* SELECT id FROM client WHERE belongs_to $first_layer_obj->id */;
        foreach ($second_layer as $second_layer_obj) {
            $array[$first_layer_obj->id][$second_layer_obj->id] = [];
            $third_layer = /* SELECT id FROM client WHERE belongs_to $second_layer_obj->id */;
            foreach ($third_layer as $third_layer_obj->id) {
                $array[$first_layer_obj->id][$second_layer_obj->id][$third_layer_obj->id] = [];
            }
        }

I am expecting the output is:

array(3) {
["1a"]=>
   array(1){
     ["3a"]=>[]
   }
["2a"]=>
   array(1){
     ["5a"]=>[]
   }
["4a"]=>[]
}
Leaben
  • 1
  • 1
    What should happen if 2a belongs to 3a and 3a belongs to 2a? – MonkeyZeus Oct 30 '18 at 19:08
  • 1
    Possible duplicate of [Build a tree from a flat array in PHP](https://stackoverflow.com/questions/8840319/build-a-tree-from-a-flat-array-in-php) – Alex Oct 30 '18 at 19:21
  • Is it safe to assume that the first item is the top item and any below will be children? Meaning the further down you go the array the lower level it is? – Andreas Oct 30 '18 at 19:22
  • @Leaben This is close but not exactly you preferred format: https://stackoverflow.com/q/47846237/2943403 – mickmackusa Oct 31 '18 at 11:54

1 Answers1

0

Certainly the first piece of advice that I have is, you should avoid performing recursive/iterated calls to your database. You should make a single call to extract all of the desired rows in a single result set and let php do the hard part.

I've decided to try a non-recursive approach. To permit this, the result set must be prepared so that "grander" children are listed first. Now, I realize that it is entirely possible that your sample data doesn't actually represent your project values and sorting cannot be used to prepare the result set adequately -- you'll have to let me know (and perhaps update your question with more accurate sample data).

[see inline comments for what's happening in my script]

*If you aren't using php7+, then my null coalescing operator ($row1['children'] ?? []) will cause issues.
You can use: (isset($row1['children']) ? $row1['children'] : []

Code: (Demo)

// use ORDER BY belongs_to DESC, id ASC ... or usort() to prepare result set
$resultset = [
    ['id' => '6a', 'belongs_to' => '5a'],
    ['id' => '5a', 'belongs_to' => '3a'],
    ['id' => '8a', 'belongs_to' => '3a'],
    ['id' => '3a', 'belongs_to' => '1a'],
    ['id' => '1a', 'belongs_to' => null],
    ['id' => '2a', 'belongs_to' => null],
    ['id' => '4a', 'belongs_to' => null],
    ['id' => '7a', 'belongs_to' => null]
];

foreach ($resultset as $index1 => &$row1) {             // make input array modifiable by reference (not working with a copy)
    if ($row1['belongs_to']) {                          // original belongs_to value is not null (not a top-level parent)
        foreach ($resultset as $index2 => $row2) {      // search for targeted parent
            if ($row2['id'] == $row1['belongs_to']) {   // parent found
                $resultset[$index2]['children'][] = [$row1['id'] => $row1['children'] ?? []];  // store original row as child
                unset($resultset[$index1]);             // remove original row (no reason to iterate it again in outer loop)
                break;                                  // halt inner loop (no reason to iterate further)
            }
        }
    } else {                                            // original belongs_to value is null (top-level parent)
        $output[$row1['id']] = $row1['children'] ?? [];  // store children to top
    }
}
var_export($output);

Output:

array (
  '1a' => 
  array (
    0 => 
    array (
      '3a' => 
      array (
        0 => 
        array (
          '5a' => 
          array (
            0 => 
            array (
              '6a' => 
              array (
              ),
            ),
          ),
        ),
        1 => 
        array (
          '8a' => 
          array (
          ),
        ),
      ),
    ),
  ),
  '2a' => 
  array (
  ),
  '4a' => 
  array (
  ),
  '7a' => 
  array (
  ),
)
mickmackusa
  • 43,625
  • 12
  • 83
  • 136