tree.blade.php
<ul>
@foreach($places as $p)
<li>
<a href="">{{ $p->name }}</a>
@if($p->children->count())
@include ('tree', ['places' => $p->children]) //recursion
@endif
</li>
@endforeach
</ul>
I have 2 rows in my database, so the 2 is child to 1, the problem is that when the first tree is printed, it returns back to the second iteration, but this second iteration is the child one to the first, so it should not be printed again, it created duplication, how should I prevent this in my blade template
updated:
controller method:
public function index()
{
$data = [];
$data['places'] = Place::with(['children', 'parent'])->get();
return view('places/index', $data);
}
There are a few options you have at this point.
1) Let Eloquent do the heavy lifting
For a small/low traffic application I would say this approach is fine but not overly efficient as it will load each relationship one by one, however, it should give you the desired results:
$data['places'] = Place::whereNull('parent_id')->with('children')->get();
Checking for the parent_id
being null
will get only the root elements.
2) Build a tree
The other option which would be a bit more efficient (DB-wise) would be to load all of the categories and build the tree in your controller:
$allPlaces = Place::all();
function getChildren($places, $place)
{
$children = $places->where('parent_id', $place->id)->all()
->map(function ($child) use ($places) {
return getChildren($places, $child);
});
$place->setRelation('children', $children);
return $place;
}
$data['places'] = $allPlaces
->filter(function ($place) {
return is_null($place->parent_id);
})
->map(function ($place) use ($allPlaces) {
return getChildren($allPlaces, $place);
});
3) Use nested sets
It might be a bit over kill at this point but it would be worth having a look at https://github.com/lazychaser/laravel-nestedset