Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Php doesn't break in a recursive foreach loop

I have a recursive function like below.

public function findnodeintree($cats,$cat_id)
{       
    foreach($cats as $node)
    {                   
        if((int)$node['id'] == $cat_id)
        {       
            echo "finded";
            $finded = $node;
            break;
        }
        else
        {
            if(is_array($node) && array_key_exists('children', $node)){ 
                $this->findnodeintree($node['children'],$cat_id);
            }
        }           
    }
    return $finded;
}

For Example

$node =$this->findnodeintree($category_Array, 169);

It gaves me

"founded"

A PHP Error was encountered

Severity: Notice

Message: Undefined variable: finded

Array Structure is like

    [0] => Array
    (
        [id] => 0
        [name] => MAIN CATEGORY
        [depth] => 0
        [lft] => 1
        [rgt] => 296
        [children] => Array
            (
                [0] => Array
                    (
                        [id] => 167
                        [name] =>  CAT 0
                        [depth] => 1
                        [lft] => 2
                        [rgt] => 17
                        [children] => Array
                            (
                                [0] => Array
                                    (
                                        [id] => 169
                                        [name] =>   CAT 1
                                        [depth] => 2
                                        [lft] => 3
                                        [rgt] => 4
                                    )

                                [1] => Array
                                    (
                                        [id] => 170
                                        [name] =>   CAT 2
                                        [depth] => 2
                                        [lft] => 5
                                        [rgt] => 10
                                        [children] => Array
                                            (
                                                [0] => Array
                                                    (
                                                        [id] => 171
                                                        [name] =>    CAT 5
                                                        [depth] => 3
                                                        [lft] => 6
                                                        [rgt] => 7
                                                    )

                                                [1] => Array
                                                    (
                                                        [id] => 172
                                                        [name] =>    CAT 3
                                                        [depth] => 3
                                                        [lft] => 8
                                                        [rgt] => 9
                                                    )

                                            )

                                    )
like image 504
orhan bengisu Avatar asked Jan 29 '13 14:01

orhan bengisu


2 Answers

To get the right value from recursion, your recursion call must not discard the return value. And since you want to walk back up the recursion tree as soon as you get a hit, and actually return the matching node, you have to break your loop at that point too.

Otherwise subsequent recursion calls overwrite your variable and the wrong node, false, or null is returned.

This should be what works:

public function findnodeintree($cats,$cat_id)
{       
    foreach($cats as $node)
    {                   
        if((int)$node['id'] == $cat_id){       
            return $node;
        }
        elseif(array_key_exists('children', $node)) {
            $r = $this->findnodeintree($node['children'], $cat_id);
            if($r !== null){
                return $r;
            }
        }           
    }
    return null;
}

Note: I removed the is_array because at that point $node has to be an array or throw an error at the first branch condition.

like image 110
dualed Avatar answered Oct 21 '22 00:10

dualed


Change your recursion line to this:

 $finded = $this->findnodeintree($node['children'],$cat_id);

You want to be able to get the line, if you recall the function, that line have to fill your variable, otherwise it will be filled in the last occuring situation but will never return the result to your first call.

Hence, $finded will be empty or non-existing in your first call.

like image 37
Tikkes Avatar answered Oct 21 '22 01:10

Tikkes