Home > Net >  PHP-Laravel foreach only loops once
PHP-Laravel foreach only loops once

Time:10-08

I have a categories table with parent_id column, referring to parent category's ID. I need to retrieve all of the ID's that are under a certain category (all of its children & grandchildren) I wrote this recursive function but for some reason it only returns the direct children of the given category id.

What am I missing here?

function subCategoriesList($id, $data=[]){
    $children = Category::whereParentId($id)->get();
    foreach ($children as $child){
        $data[] = $child->id;
        subCategoriesList($child->id, $data);
    }
    return $data;
}

CodePudding user response:

You're not passing $data by reference, but you're making the recursive call as if you are.

Try:

function subCategoriesList($id){
    $data=[]
    $children = Category::whereParentId($id)->get();
    foreach ($children as $child){
        $data[] = $child->id;
        $data = array_merge($data, subCategoriesList($child->id));
    }
    return $data;
}

Conversely, and for completeness, with references:

function subCategoriesList($id, &$data){
    $children = Category::whereParentId($id)->get();
    foreach ($children as $child){
        $data[] = $child->id;
        subCategoriesList($child->id, $data);
    }
}

// You must call it as follows, though
$my_data = [];
subCategoriesList($some_id, $my_data);

Personally, though, I tend to recommend that references be avoided unless there is a clear reason for them. IMO they tend to result in confusing code and side-effects, while rarely delivering the benefits that the writer thinks they are getting.

CodePudding user response:

You're not doing anything with the returndata when you call subCategoriesList within the function.

subCategoriesList($child->id, $data);

should be

$data = array_merge($data, subCategoriesList($child->id, $data));
  • Related