laravel-nestedset
laravel-nestedset copied to clipboard
Multiple root nodes eager loaded tree
Hello, first: thanks for this great package. Really cool eloquent and collection work here. My goal is to display a tree with multiple root nodes, not particularly node 0 or same level root. I can make it work, but it could be performance improved (eloquent).
My case
-
see the attached tree
-
My nestedset Category model belongsToMany User model (many to many with pivot)
-
My User is attached to node 1, 5 and 7 (attached tree)
-
I need a tree with 3 root nodes and their respective children & descendants. So a user has one or multiple "virtual" root node(s) (not especially node 0, nor same level nodes).
-
User should get a tree having:
- 3 root nodes (1, 5 & 7) at tree top level
- children and ancestors under node 1 and 5
- nothing under root node 7
What is working
I can manage to get my multiple root node tree with their descendants with a foreach
. But I can't get a eager loading of all descendants from all root nodes in one optimised query.
$categories = $user()->categories()->get(['categories.id']); //all node from given user
$nodes = collect([]);
foreach ($categories as $node) {
$nodes = $nodes->merge(Category::descendantsAndSelf($node->id)->toTree());
}
This returns the correct tree:
- Nodes 1, 5 & 7 as root nodes (multiple top level)
- Nodes 1 & 5 have all their children and descendants
- Node 7 is here as top level, without any children
What is not working
I tried multiple things to eager-load multiple nodes with their descendants.
$user_nodes = $user->categories()->pluck('id')->toArray(); //array of nodes ID
$tree = Category::whereIn('id', $user_nodes )->with('descendants');
$nodes = $tree->get()->toTree();
will return few of the root node, without any descendant
- returns a tree with node 1 and 5 only, without descendants
- missing node 7 (on my test database with more nodes, only the 3 first of 8 root node shows, without any descendants)
$nodes = Auth::user()->categories()->with('descendants');
$tree = $nodes->get()->toTree();
will return same result as before
few tests
$tree= Category::where('id', 1)->with('descendants')->get()->toTree();
Will only generate a tree with root Node 1, without any children (nodes 3 & 4) or ancestors (node 8), but there are some :
$nodes = Category::descendantsAndSelf(1)->toTree();
returns a correct tree with node 1 as root and with children (nodes 3 & 4) and descendants (node 8).
what would be needed
-
Category::descendantsAndSelf()
accept and array of node ID, and generate an eloquent request that load categories nodes and eager-load descendants (descendantsAndSelfves) (it seems complex to implement seeingnamespace Kalnoy\Nestedset\QueryBuilder; whereDescendantOf()
) -
Auth::user()->categories()->with('descendants')->get()->toTree();
eloquent or collection trick to get the multi root nodes full tree
Maybe I'm missing something when starting from a classic eloquent query to get a full tree. My improvements research seems related to #388.
Any advice would be much appreciated!
Thank you for your attention and your help.