====== Requête récursive ======
Prenons le cas d'une table **familles** avec des enregistrements liés parent/enfant sur plusieurs niveaux
id | nom | id_parent
-----------------------------
1 | grand parent | null
2 | parent | 1
3 | enfant 1 | 2
4 | enfant 2 | 2
etc...
Si on crée une relation simple dans le model, on obtient uniquement les enfants sur un seul niveau. On va créer une méthode qui s'appelle elle même
hasMany(Famille::class, 'id_parent', 'id');
}
public function recursiveChildren() {
return $this->childrens()->with('recursiveChildren');
// si vous voulez trier par nom
return $this->childrens()->orderBy('nom')->with('recursiveChildren');
}
}
La requête eloquent pour sortir un résultat correcte est la suivante
Famille::with('recursiveChildren')->whereNull('id_parent')->get()
On utilise le with() pour forcer l'exécution de la relation pour chaque enregistrement et on filtre sur le id_parent sur null pour commencer uniquement sur le 1er niveau
On obtient ce résultat
=> Illuminate\Database\Eloquent\Collection {
all: [
App\Models\Famille {
id: 1,
nom: "grand parent",
id_parent: null,
recursiveChildren: Illuminate\Database\Eloquent\Collection {
all: [
App\Models\Famille {
id: 2,
nom: "parent",
id_parent: 1,
recursiveChildren: Illuminate\Database\Eloquent\Collection {
all: [
App\Models\Famille {
id: 3,
nom: "enfant 1",
id_parent: 2,
recursiveChildren: Illuminate\Database\Eloquent\Collection {
all: [],
},
},
App\Models\Famille {
id: 4,
nom: "enfant 2",
id_parent: 2,
recursiveChildren: Illuminate\Database\Eloquent\Collection {
all: [],
},
},
],
},
},
],
},
},
],
}
Maintenant on veut afficher le résultat. Il va falloir créer une sous-vue pour la récursivité.
Controller
public function index(){
$familles = Famille::with('recursiveChildren')->whereNull('id_parent')->orderBy('nom')->get();
return view('famille', compact('familles'));
}
Vue: famille.blade.php
Vue: famille-item.blade.php
@if(isset($famille->recursiveChildren) and count($famille->recursiveChildren))
@php
// adaptez comme vous le souhaitez
$tab .= '⋅ ';
@endphp
@foreach ($famille->recursiveChildren as $element)
@include('visu.groupe-item', ['famille'=>$element, 'tab'=>$tab])
@endforeach
@endif
Pour un affichage en liste avec ul et li
Vue: famille.blade.php
@foreach ( $familles as $e )
@include('famille-item', ['famille'=>$e])
@endforeach
Vue: famille-item.blade.php
{!! $tab !!}{{ $famille->nom }}
@if(isset($famille->recursiveChildren) and count($famille->recursiveChildren))
@foreach ($famille->recursiveChildren as $element)
@include('visu.groupe-item', ['famille'=>$element])
@endforeach