metad00r
metad00r

Reputation: 134

PHP - Recursive function to loop array with unknown depth is not passing/persisting the parent keys after two levels

I would like some advice on how to deal with this use case:

I have the following multidimentional test array with unknow depth:

$entries =
[
    [
        'id' => 'Foo',
        'parent' => 'root',
        'logic_rules' => []
    ],
    [
        'id' => 'Bar',
        'parent' => 'root',
        'logic_rules' => [],
        'children' => [
            [
                'id' => 'Foobar',
                'parent' => 'Bar',
                'logic_rules' => [],
                'children' => [
                    [
                        'id' => 'Foobar2',
                        'parent' => 'Foobar',
                        'logic_rules' => [],
                        'children' => [
                            [
                                'id' => 'Foobar3',
                                'parent' => 'Foobar2',
                                'logic_rules' => []
                            ]
                        ]
                    ]
                ]
            ]
        ]
    ]
];

And I try to traverse the array to execute some logic (excluded from the example), with this recursive function:

function traverse(array $entries, array &$result = [])
{
    foreach ($entries as $k => $value) {
        // If `logic_rules` exists proceed executing the logic
        // and store the result in the same `parent -> id` position
        if (array_key_exists('logic_rules', $value)) {
            $result[$value['parent']][$value['id']]['logic_rules'] = time(); // some logic
        }

        // Re-loop if is parent
        if (array_key_exists('children', $value)) {
            traverse($value['children'], $result);
        }
    }

    return $result;
}

The output of traverse($entries) is:

Array
(
    [root] => Array
        (
            [Foo] => Array
                (
                    [logic_rules] => 1603091236
                )

            [Bar] => Array
                (
                    [logic_rules] => 1603091236
                )

        )

    [Bar] => Array
        (
            [Foobar] => Array
                (
                    [logic_rules] => 1603091236
                )

        )

    [Foobar] => Array
        (
            [Foobar2] => Array
                (
                    [logic_rules] => 1603091236
                )

        )

    [Foobar2] => Array
        (
            [Foobar3] => Array
                (
                    [logic_rules] => 1603091236
                )

        )

)

But I expect this:

Array
(
    [root] => Array
        (
            [Foo] => Array
                (
                    [logic_rules] => 1603091236
                )

            [Bar] => Array
                (
                    [logic_rules] => 1603091236

                    [Foobar] => Array
                        (
                            [logic_rules] => 1603091236

                            [Foobar2] => Array
                                (
                                    [logic_rules] => 1603091236

                                    [Foobar3] => Array
                                        (
                                            [logic_rules] => 1603091236
                                        )
                                )
                        )
                )

        )
)

Seems like it's skipping its ancestors. Any advice on this?

Upvotes: 2

Views: 321

Answers (1)

Robin Gillitzer
Robin Gillitzer

Reputation: 1602

The solution is to refer to the results parent so the following depth will push to it.

Look at this line:

traverse($value['children'], $result[$value['parent']]);

This code will work for you:

function traverse (array $entries, array &$result = []) {
  foreach ($entries as $value) {
    
      // add your logical stuff here
      $result[$value['parent']][$value['id']] = array(
        'logical_rules' => time()
      );

    if (array_key_exists('children', $value)) {
      traverse($value['children'], $result[$value['parent']]);
    }
  }
  return $result;
}

Upvotes: 1

Related Questions