Laravel – How to get all nested subcategories recursively

I want to get IDs of all nested sub-categories.

The database tables are following

categories

id | name       | parent_id 
-----------------------------
1  | Electronics| null  
2  | media      | 1
3  | Clothing   | null  
4  | Craft      | null
5  | Mens       | 3
6  | Women      | 3
7  | Shirt      | 5
8  | Jeans      | 5
9  | speaker    | 2
10 | DVDs       | 2
11 | Computers  | 1

Lets i have a Category Electronics, My task is to get IDs of its sub-categories and deep down to last level of it.
I am trying the following

Category model

public function subCategory(){
    return $this->hasMany(Category::class, 'parent_id');
}

public function recursiveChildren()
{
    return $this->subCategory()->with('recursiveChildren');
}

ProductController
$cate_id        = 1 // Electronics
$categoriesID   = Category::with('recursiveChildren')->where('id', $cat_id)->pluck("id");
echo '<pre>'; print_r($categoriesID); die;

I am getting follwing result:
IlluminateSupportCollection Object
(
    [items:protected] => Array
        (
            [0] => 6
        )

)

I want to achieve following:
Array(
    [0] => 1
    [1] => 2
    [2] => 9
    [3] => 10
)

Please correct me. Thank you

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

After some research I have found the solution


Category Model

public function subcategories(){
    return $this->hasMany(Category::class, 'parent_id');
}

public function children(){
    return $this->subcategories()->with('children');
}

public function hasChildren(){
    if($this->children->count()){
        return true;
    }
    return false;
}

public function findDescendants(Category $category){
    $this->descendants[] = $category->id;

    if($category->hasChildren()){
        foreach($category->children as $child){
            $this->findDescendants($child);
        }
    }
}

public function getDescendants(Category $category){
    $this->findDescendants($category);
    return $this->descendants;
}

Controller
$category = Category::find($cat_id);
$category_ids = $category->getDescendants($category);
echo '<pre>'; print_r($categoriesID); die;

I have found the solution here

Method 2

It can be tricky to this manually. You’ll bounce between “it works but it’s slow” and “it’s fast… but it doesn’t work anymore”.

You best bet is to use this wonderful package https://github.com/staudenmeir/laravel-adjacency-list. It adds several relationships that uses CTE queries, which are far too complex to be described in a few words here (and are off topic) but pretty useful when it comes to recursion.

The good news is that with this package, all this is pretty simple.

From the documentation:

Included Relationships

The trait provides various relationships:

  • ancestors(): The model’s recursive parents.
  • ancestorsAndSelf(): The
    model’s recursive parents and itself.
  • children(): The model’s direct
    children.
  • childrenAndSelf(): The model’s direct children and itself.
  • descendants(): The model’s recursive children. descendantsAndSelf():
    The model’s recursive children and itself.
  • parent(): The model’s
    direct parent.
  • parentAndSelf(): The model’s direct parent and itself.
  • rootAncestor(): The model’s topmost parent. siblings(): The parent’s
    other children.
  • siblingsAndSelf(): All the parent’s children.

If you want to learn more on this topic, you can check this package, https://github.com/staudenmeir/laravel-cte, by the same author, which is a dependency of the previous one.

Another reading on CTE queries: https://www.geeksforgeeks.org/mysql-recursive-cte-common-table-expressions/


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x