In-memory Tree Shaping

When you've already fetched a flat result, build the tree without extra queries. Every get() on a NodeTrait model returns a NodeCollection, which knows how to assemble itself.

The flat → tree transform

$flat = Category::query()->defaultOrder()->get();
// → Collection of 9 categories ordered by lft:
//   Electronics, Computers, Laptops, Desktops, Phones, Android,
//   Books, Fiction, Non-fiction

$tree = $flat->toTree();

$tree is a collection of the top-level nodes only, each with its children relation populated recursively:

$tree->count();                                // 2 — Electronics, Books
$tree[0]->name;                                // 'Electronics'
$tree[0]->children->count();                   // 2 — Computers, Phones
$tree[0]->children[0]->children->count();      // 2 — Laptops, Desktops

No extra queries fire — toTree() walks the already-loaded collection and rewires the relations using the lft / rgt ranges.

Flat-with-hierarchy

toFlatTree() returns a single flat collection in depth-first order with parent and children relations populated — handy when you want to render a tree with <ul>-style indenting but don't want to recurse:

foreach ($flat->toFlatTree() as $node) {
    echo str_repeat('  ', $node->depth) . $node->name . "\n";
}
// Electronics
//   Computers
//     Laptops
//     Desktops
//   Phones
//     Android
// Books
//   Fiction
//   Non-fiction

Subtree shaping

Both toTree() and toFlatTree() accept an optional $root argument when your collection is a subtree, not the whole table. Without it, the implicit root is inferred from the smallest-lft node's parent_id.

// Just Electronics + descendants, shaped as a subtree
$subtree = Category::query()
    ->whereDescendantOrSelf($electronics->getBounds())
    ->defaultOrder()
    ->get()
    ->toTree($electronics);

Linking nodes without restructuring

If you want the relations populated on the original flat collection — e.g. so each node can call ->parent or ->children without lazy loading — but don't want to re-shape into a tree, call linkNodes():

$flat->linkNodes();
$flat[3]->parent->name;                  // resolved without a query
$flat[0]->children->pluck('name');       // ['Computers', 'Phones']

toTree() calls linkNodes() internally, so the relations are already populated on the tree result too.