Matt Komarnicki
Matt Komarnicki

Reputation: 5422

Laravel 5.7: How to recursively get an attribute from a nested Eloquent relationship?

First of all, I don't have any issues with setting up the relationship within the model.

I have a WebGroup model that can have unlimited parent WebGroup(s) as well as unlimited child WebGroup(s).

Parent relationship:

public function parent()
{
    return $this
        ->belongsTo(WebGroup::class, 'pargroup1', 'webgroup')
        ->with('parent');
}

Child relationship:

public function children()
{
    return $this
        ->hasMany(WebGroup::class, 'pargroup1', 'webgroup')
        ->with('children');
}

I can get a nested collection of all children for a given WebGroup via: $webGroup->children.

This gives me:

enter image description here

It's nested, it's unlimited. Fantastic. But now how can I recursively loop through that collection and recursively get a flatten array of a given attribute. For example each WebGroup model has a name attribute.

How to recursively get all names for a given collection of all WebGroups starting from parent, going down to all children down the rabbit hole?

Upvotes: 0

Views: 2023

Answers (3)

Here is the code to get all the childrens of the selected parent...

// Recursive function to get all children/sub-categories ids

function getRecursiveCategoryId($categoryId){ // Your Parent Category Id

    $children = [];
    $parentCategories = Category::where('parent_id', $categoryId)
                    ->latest()
                    ->select('id')
                    ->get();

    foreach ($parentCategories as $category) {

    $children[] = $category->id;


    $children[$category->id] = getRecursiveCategoryId($category->id,$children);
    
    }
                    
    return $children;                        
}

$arraySubCategoryIds = getRecursiveCategoryId($categoryId);

$arraySubCategoryIdss = Arr::flatten($arraySubCategoryIds);

Upvotes: 0

Viraj Amarasinghe
Viraj Amarasinghe

Reputation: 941

The easiest way to do this using appends variable. Get the children data using mutator like this,

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

and then use the appends variable,

protected $appends = ['children'];

Then just call the function,

Category::find($id)

enter image description here

Upvotes: 0

Matt Komarnicki
Matt Komarnicki

Reputation: 5422

OK, I managed to write this by myself…

private function getNestedChildrenByWebGroup(WebGroup $webGroup): Collection
{
    $data = collect([]);

    foreach ($webGroup->children as $child) {
        $data->push($child->webgroup);

        // If child has it's own children…
        if ($child->children instanceof Collection) {

            // Recursive call to all children of a child
            foreach ($child->children as $childWebGroup) {
                $this->getNestedChildrenByWebGroup($childWebGroup);
                $data->push($childWebGroup->webgroup);
            }
        }
    }

    return $data;
}

DB Structure:

enter image description here

Final result:

enter image description here

enter image description here

Upvotes: 1

Related Questions