Trying to create a hierarchy of arrays of objects, but recursion function is failing. On closer inspection, it appears to go deeper into the tree, but once it runs out of children it doesn't go back a previous level and keep recursing.

The function tries to add a child object to a parent object by searching through the hierarchy, identifying the parent and then adding a child based on the id and type properties matching the request.

Here is an example hierarchy:

    Array
(
[0] => DataObject Object
    (
        [id:DataObject:private] => 1
        [type:DataObject:private] => Collection
        [properties:DataObject:private] => Array
            (
                [title] => Collection One
            )

        [childObjects:DataObject:private] => Array
            (
                [0] => DataObject Object
                    (
                        [id:DataObject:private] => 6
                        [type:DataObject:private] => Item
                        [properties:DataObject:private] => Array
                            (
                                [title] => Item Six
                            )

                        [childObjects:DataObject:private] => Array
                            (
                            )

                    )

                [1] => DataObject Object
                    (
                        [id:DataObject:private] => 11
                        [type:DataObject:private] => Item
                        [properties:DataObject:private] => Array
                            (
                                [title] => Item Eleven
                            )

                        [childObjects:DataObject:private] => Array
                            (
                            )

                    )

                [2] => DataObject Object
                    (
                        [id:DataObject:private] => 10
                        [type:DataObject:private] => Item
                        [properties:DataObject:private] => Array
                            (
                                [title] => Item Ten
                            )

                        [childObjects:DataObject:private] => Array
                            (
                            )

                    )

                [3] => DataObject Object
                    (
                        [id:DataObject:private] => 14
                        [type:DataObject:private] => Item
                        [properties:DataObject:private] => Array
                            (
                                [title] => Item Fourteen
                            )

                        [childObjects:DataObject:private] => Array
                            (
                            )

                    )

                [4] => DataObject Object
                    (
                        [id:DataObject:private] => 1
                        [type:DataObject:private] => ItemGroup
                        [properties:DataObject:private] => Array
                            (
                                [item_group_title] => 1
                                [item_group_depth] => 0
                                [item_group_parent_id] => 
                            )

                        [childObjects:DataObject:private] => Array
                            (
                                [0] => DataObject Object
                                    (
                                        [id:DataObject:private] => 7
                                        [type:DataObject:private] => Item
                                        [properties:DataObject:private] => Array
                                            (
                                                [title] => Item Seven
                                            )

                                        [childObjects:DataObject:private] => Array
                                            (
                                            )

                                    )

                                [1] => DataObject Object
                                    (
                                        [id:DataObject:private] => 1
                                        [type:DataObject:private] => Item
                                        [properties:DataObject:private] => Array
                                            (
                                                [title] => Item One
                                            )

                                        [childObjects:DataObject:private] => Array
                                            (
                                            )

                                    )

                                [2] => DataObject Object
                                    (
                                        [id:DataObject:private] => 2
                                        [type:DataObject:private] => ItemGroup
                                        [properties:DataObject:private] => Array
                                            (
                                                [item_group_title] => 1.1
                                                [item_group_depth] => 1
                                                [item_group_parent_id] => 1
                                            )

                                        [childObjects:DataObject:private] => Array
                                            (
                                                [0] => DataObject Object
                                                    (
                                                        [id:DataObject:private] => 8
                                                        [type:DataObject:private] => Item
                                                        [properties:DataObject:private] => Array
                                                            (
                                                                [title] => Item Eight
                                                            )

                                                        [childObjects:DataObject:private] => Array
                                                            (
                                                            )

                                                    )

                                            )

                                    )

                                [3] => DataObject Object
                                    (
                                        [id:DataObject:private] => 5
                                        [type:DataObject:private] => ItemGroup
                                        [properties:DataObject:private] => Array
                                            (
                                                [item_group_title] => 1.4
                                                [item_group_depth] => 1
                                                [item_group_parent_id] => 1
                                            )

                                        [childObjects:DataObject:private] => Array
                                            (
                                                [0] => DataObject Object
                                                    (
                                                        [id:DataObject:private] => 2
                                                        [type:DataObject:private] => Item
                                                        [properties:DataObject:private] => Array
                                                            (
                                                                [title] => Item Two
                                                            )

                                                        [childObjects:DataObject:private] => Array
                                                            (
                                                            )

                                                    )

                                            )

                                    )

                            )

                    )

            )

    )

)

Where the function fails is trying to add ItemGroup 11 to ItemGroup 5. This is because the function recurses through the array like this:

  • Collection One
    • Item Six
    • Item Eleven
    • Item Ten
    • Item Fourteen
    • ItemGroup One
    • Item Seven
    • Item One
    • ItemGroup Two
      • Item Eight (finishes here)

If it came back out after finding no children on Item eight it would see that the next object is ItemGroup Five which is what we're looking for.

Hopefully that's clear what I'm trying to do, and I'm assuming it's obvious, but the recursive function I'm using doesn't ever drop back a level. Here's the function:

  public function addChildObjToParentObj(array $objArray, DataObject $newParentObj, DataObject $newChildObj) {

    // check if current array has correct DataObject
    if (is_array($objArray)) {
        foreach ($objArray as $key => $val) {

            if (is_object($val) && $val instanceof DataObject) {

                // check if id matches
                if ($val->getId() === $newParentObj->getId()) {
                    echo "ID " . $val->getId() . " matches!<br>";

                    // check if type matches
                    if ($val->getType() === $newParentObj->getType()) {
                        echo "Type " . $val->getType() . " matches!<br>";

                        // object found that matches parent, add child to it
                        $val->addChildObject($newChildObj);
                        return TRUE;
                    }
                }

                // perform recursive search through objects children
                if ($val->getChildObjects()) {
                    $childObjects = $val->getChildObjects();
                    return $this->addChildObjToParentObj($childObjects, $newParentObj, $newChildObj);
                }
            }
        }
    }
}

I've seen other people use a level variable to track depth, but I don't want to implement that unless I have to, was hoping that the recursion would handle this for me. Any takers? :)

有帮助吗?

解决方案

Your code looked good to me and it got me curious. I mocked up a simple version using all arrays instead of objects and stumbled upon the fix:

return $this->addChildObjToParentObj($childObjects, $newParentObj, $newChildObj);

Take out the return on this line and it should work. I didn't realize it at first but the return causes it to halt execution at the point where you need to go back a previous level.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top