0

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;
}
1

2 Answers 2

1

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.

Sign up to request clarification or add additional context in comments.

3 Comments

I didn't know I had to do that! Thanks so much! It's returning same child category 6 times but nothing I can't handle 😂 there was an array_unique function for that I believe.
Well unless there's a subcategory that has 6 parents, there's probably a logic issue in there to be resolved. I didn't have any usable test data to actually run while I wrote this.
Oh I think we need to get rid of $data from the parameter list. There's no need for it to be there in the non-reference version.
1

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));

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.