skip to Main Content

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

2

Answers


  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.

    Login or Signup to reply.
  2. 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));
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search