简体   繁体   中英

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
                                                    )

                                            )

                                    )

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.

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.

The recursive call findnodeintree will go through certain loops will not "find" anything and yet they still return a variable $finded. Except that since in their loop it was never found, that variable is indeed not declared. Try this:

public function findnodeintree($cats,$cat_id)
{       
    $finded = NULL;
    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;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM