0

I have a PHP array that outlines a parent-child relationships between objects, based on their ID. The array could potentially be infinitely deep, but the only rule is that "you may not add a child ID to a parent, where the child ID is a parent or grandparent (or great-grandparent etc etc) of said parent", in order to rule out recursive loops.

For example:

<?php
// Good relationship: 6 and 4 are children of 7, with 5 a child of 6 and so on
$good_relationship = [
    'id' => 7,
    'children' => [
        [
            'id' => 6,
            'children' => [
                [
                    'id' => 5,
                    'children' => [.. etc etc..]
                ]
            ]
        ],
        [
            'id' => 4,
            'children' => []
        ]
    ]
];



// Badly-formed relationship: 6 is a child of 7, but someone added 7 as a child of 6.
$bad_relationship = [
    'id' => 7,
    'children' => [
        [
            'id' => 6,
            'children' => [
                [
                    'id' => 7,
                    'children' => [ ... 6, then 7 then 6 - feedback loop = bad ... ]
                ]
            ]
        ],
        [
            'id' => 4,
            'children' => []
        ]
    ]
];
?>

I'm trying to write a function that checks for recursion issues when an ID is potentially added as a child to another ID. It would take in an ID ($candidate_id) and tries to add it as a child of another ID ($parent_id), and checks the existing array ($relationship) all the way back up the chain, and returns true if the candidate does not show up as a parent,grandparent,etc of $parent, and false if the candidate addition will cause a recursion issue by being added.

From the above $good_relationship, it would return true is I added ID 3 to ID 5, but false if I added ID 7 to ID 5.

Here's what I have so far, but I know it's way off - it's only checking for immediate grandparent of the candidate ID.

<?php

public function check_candidate($array, $candidate_id, $parent_id, &$grandparent_id = 0)
{
    $reply_array = [];
    foreach($array as $action)
    {

        // If $action['id'] is the same as the grandparent,
        if($grandparent_id == $action['id'])
        {
            return false;
        }

        $grandparent_id = $action['id'];


        if(isset($action['children']) && count($action['children']) >= 1)
        {
            $this->check_candidate($action['children'], $candidate_id, $parent_id, $grandparent_id);
        }
    }


    return true;
}

?>

I've had a look at array_walk_recursive() in this case, but if $good_relationship has more than 1 element to it (which it always will), the callback will not know how 'deep' it is within the function, and it all becomes a bit of a nightmare.

Can anyone help me here?

5
  • maybe I am simplifying things too much but couldn't you recursively look for a parent until no more parent is present? Meanwhile checking and returning when you have to. Commented Sep 8, 2014 at 20:36
  • Cheers RST - it appears PHP's array handling doesn't have a native function where you can reference an array's parent. I've found another SO question that will get me past the line for this issue - sharing link as the answer. Commented Sep 9, 2014 at 22:51
  • Maybe it is easier to do array_flip or array_values and then check for isset or something. There are some examples posted to www.php.net that might meet your requirements. Commented Sep 10, 2014 at 11:07
  • Cheers RST - array_flip and array_values seem to have been built to only handle one-dimensional arrays, but I see what you mean. Thanks Commented Sep 10, 2014 at 19:45
  • possible duplicate of PHP - Find parent key of array Commented Sep 14, 2014 at 13:41

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.