jacobdo
jacobdo

Reputation: 1615

Output folder tree using blade from laravel collection

Suppose I have the following laravel collection:

[
 {id: 1, name: 'Home', folder_id: null},
 {id: 2, name: 'Documents', folder_id: 1},
 {id: 3, name: 'Media', folder_id: 1 },
 {id: 4, name: 'Photos', folder_id: 3},
 {id: 5, name: 'Videos', folder_id: 3},
 {id: 6, name: 'Invoices', folder_id: 2},
 {id: 7, name: 'Games', folder_id: 1}
]

folder_id is a foreign key is a row to the direct parent.

I would like to iterate through the collection and create a folder tree looking like this using blade templating engine:

Each element in the collection is of instance Folder with the following eloquent relationships defined:

public function folder(){
    return $this->belongsTo(Folder::class);
}

public function folders(){
    return $this->hasMany(Folder::class);
}

Upvotes: 0

Views: 1878

Answers (2)

jacobdo
jacobdo

Reputation: 1615

After hours of while loops and other silliness, I finally realised the power of blade's partials.

First I define the initial loop and output all top level folders i.e. those that have folder_id (Parent folder id) of null.

@foreach($folders as $folder)
        @if($folder->folder_id == null)
            @include('folder', $folder)
        @endif
@endforeach

In the folder.blade.php partial I have the following code:

<div class="folder" style="padding-left: 10px">
    <div class="name">{{ $folder->name }}</div>
    @if($folder->folders)
        @foreach($folder->folders as $child_folder)
            @include('folder', ['folder' => $child_folder])
        @endforeach
    @endif
</div>

In the partial, I check whether the given folder has children and if it does, I include partial for each of folder's children once again.

Upvotes: 1

Mahdi Younesi
Mahdi Younesi

Reputation: 7489

Add this to Folder model class

public function children()
{
    return $this->hasMany(Folder::class,'folder_id','id');
}

public function parent()
{
    return $this->belongsTo(Folder::class,'id','folder_id');
}

Then in controlle pass all to view

return view('view')->with(['folders'=>Folder::with('parent','children')->all()]);

And in view this will do the heck

<ul>
 @foreach($folders as $folder)
 {
   @foreach($folder->children as $child)
       //you can get child parent via $child->parent
   @endforeach

   //do whatever you want
 }
</ul>

Upvotes: 0

Related Questions