A modern Laravel implementation of the nested-set model for hierarchical data — strict types throughout, PHPStan level 9, atomic CASE-WHEN mutations, multi-tree scoping, soft-delete cascade, live aggregate roll-ups, and an opinionated repair toolkit.
$root = Category::create(['name' => 'Root']);
$root->saveAsRoot();
$child = Category::create(['name' => 'Child']);
$child->appendToNode($root)->save();
Category::query()->whereDescendantOf($root->getBounds())->get();
$root->descendants()->orderBy('lft')->get();
$root->refresh()->getSubtreeSize(); // rgt - lft + 1Declare aggregates on the model and the SUM / COUNT / AVG / MIN / MAX roll-ups are maintained automatically as the tree changes:
#[NestedSetAggregate(column: 'tickets_total', sum: 'tickets')]
#[NestedSetAggregate(column: 'tickets_count', count: true)]
class Area extends Model implements HasNestedSet { use NodeTrait; }
$region->tickets_total; // SUM of `tickets` across the subtree — maintained on save / move / delete
Area::query()->withFreshAggregates()->get(); // correlated re-read for drift detectionThe nested-set encoding stores lft and rgt integers on every node so any
subtree, ancestor chain, or descendant set is a single BETWEEN query — no
recursive CTEs, no N+1 loops. The price is that mutations (insert / move /
delete) have to shift many rows to keep the lft/rgt sequence dense, so it's
best suited to read-heavy hierarchies: category trees, menu structures,
org charts, comment threads.
This package executes every shift as a single CASE WHEN UPDATE, so even a
subtree move that touches thousands of rows is one round trip.
composer require vusys/laravel-nestedsetThe service provider auto-registers Blueprint macros and registers a publishable config file:
php artisan vendor:publish \
--provider="Vusys\NestedSet\NestedSetServiceProvider" \
--tag=nestedset-configSee the Installation guide for the rest of the setup (migration macros, model trait, scoped trees).
Full documentation lives at https://vusys.github.io/laravel-nestedset/.
- Getting Started — Introduction · Installation · Migration · Primary Keys · Model Setup
- Tree Operations — Inserting & Moving · Soft Deletes · Bulk Insertion
- Querying — Tree Queries · Eloquent Relations · In-memory Tree Shaping · Inspection · Scoped Trees
- Aggregates — Overview · Setup · Reading · Declaring · Filtered · Listeners · Recipes · Maintenance · Drift & Limitations
- Maintenance — Tree Repair · Repairing Aggregates · Corruption Reference
- Reference — Configuration · Testing Helpers · Transactions · Production Notes · vs. kalnoy/nestedset
The site is built from the markdown in docs/ — if you spot an
error, edit the source and open a PR.
Run the full check suite before opening a PR:
composer pint:check # style
composer rector:check # automated refactors
composer analyse # static analysis
composer test # unit + featureAll four must pass on CI before merge.
MIT. See LICENSE.