PHPackages                             vusys/laravel-nestedset - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Database &amp; ORM](/categories/database)
4. /
5. vusys/laravel-nestedset

ActiveLibrary[Database &amp; ORM](/categories/database)

vusys/laravel-nestedset
=======================

Nested set model implementation for Laravel 11+.

v0.24.4(2w ago)0381[2 PRs](https://github.com/Vusys/laravel-nestedset/pulls)MITPHPPHP ^8.3CI passing

Since May 12Pushed 1w agoCompare

[ Source](https://github.com/Vusys/laravel-nestedset)[ Packagist](https://packagist.org/packages/vusys/laravel-nestedset)[ RSS](/packages/vusys-laravel-nestedset/feed)WikiDiscussions master Synced 1w ago

READMEChangelog (10)Dependencies (63)Versions (100)Used By (0)

vusys/laravel-nestedset
=======================

[](#vusyslaravel-nestedset)

[![Tests](https://github.com/Vusys/laravel-nestedset/actions/workflows/tests.yml/badge.svg)](https://github.com/Vusys/laravel-nestedset/actions/workflows/tests.yml) [![codecov](https://camo.githubusercontent.com/469e7e45681996bde068ed43b2d5841a4f487b68e942cd93f2163fd5c6c2d505/68747470733a2f2f636f6465636f762e696f2f67682f56757379732f6c61726176656c2d6e65737465647365742f67726170682f62616467652e737667)](https://codecov.io/gh/Vusys/laravel-nestedset) [![tests](https://camo.githubusercontent.com/03b42cf3f8296a9294b73d851470152474af4170c419a9917f96d8638f53e6e6/68747470733a2f2f696d672e736869656c64732e696f2f656e64706f696e743f75726c3d68747470733a2f2f7261772e67697468756275736572636f6e74656e742e636f6d2f56757379732f6c61726176656c2d6e65737465647365742f6261646765732f74657374732e6a736f6e)](https://github.com/Vusys/laravel-nestedset/actions/workflows/tests.yml) [![assertions](https://camo.githubusercontent.com/47ec7184430407aefd46f0eb3fc98e3b5b70a5b59fdf448aafa59defa3d85608/68747470733a2f2f696d672e736869656c64732e696f2f656e64706f696e743f75726c3d68747470733a2f2f7261772e67697468756275736572636f6e74656e742e636f6d2f56757379732f6c61726176656c2d6e65737465647365742f6261646765732f617373657274696f6e732e6a736f6e)](https://github.com/Vusys/laravel-nestedset/actions/workflows/tests.yml) [![test LOC](https://camo.githubusercontent.com/7643c0c22687204ed4e97c693ca5c511be6d947b425d3e663479847aed6059ae/68747470733a2f2f696d672e736869656c64732e696f2f656e64706f696e743f75726c3d68747470733a2f2f7261772e67697468756275736572636f6e74656e742e636f6d2f56757379732f6c61726176656c2d6e65737465647365742f6261646765732f746573742d726174696f2e6a736f6e)](tests/) [![CI matrix](https://camo.githubusercontent.com/45eca337daaf94d15db7c6f2be6cdab3b0a4231f2f2dfb37d2f93495dfce4ddf/68747470733a2f2f696d672e736869656c64732e696f2f656e64706f696e743f75726c3d68747470733a2f2f7261772e67697468756275736572636f6e74656e742e636f6d2f56757379732f6c61726176656c2d6e65737465647365742f6261646765732f6d61747269782e6a736f6e)](.github/workflows/tests.yml) [![Bencher](https://camo.githubusercontent.com/782b689d97ac54894eef72794a5b361a5954c3cc650990a0e73a97a0ef619bb7/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f42656e636865722d747261636b65642d4644364631423f6c6f676f3d646174613a696d6167652f7376672b786d6c3b6261736536342c50484e325a79423462577875637a30696148523063446f764c336433647935334d793576636d63764d6a41774d43397a646d636949485a705a58644362336739496a41674d4341794e4341794e4349675a6d6c73624430696432687064475569506a78775958526f49475139496b30784d69417954444d674e3359784d477735494455674f533031566a64614969382b5043397a646d632b)](https://bencher.dev/perf/vusys-laravel-nestedset) [![Mutation testing](https://camo.githubusercontent.com/2feb4333774a95a812df2cf7ea1ce094135678e47b2d3f305d914aded3794699/68747470733a2f2f696d672e736869656c64732e696f2f656e64706f696e743f7374796c653d666c61742675726c3d68747470733a2f2f62616467652d6170692e737472796b65722d6d757461746f722e696f2f6769746875622e636f6d2f56757379732f6c61726176656c2d6e65737465647365742f6d6173746572)](https://dashboard.stryker-mutator.io/reports/github.com/Vusys/laravel-nestedset/master) [![OpenSSF Scorecard](https://camo.githubusercontent.com/90b85119aaebab4770f68a672f5c76ad6df5ef51bea0451b51c683bf2fceb6ad/68747470733a2f2f6170692e73636f7265636172642e6465762f70726f6a656374732f6769746875622e636f6d2f56757379732f6c61726176656c2d6e65737465647365742f6261646765)](https://scorecard.dev/viewer/?uri=github.com/Vusys/laravel-nestedset) [![PHP](https://camo.githubusercontent.com/c9b19f1cbf8aefb8c278c8b5d392b64401164a08fced6ccbf376b32135d6714f/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f7068702d253545382e332d3737374242343f6c6f676f3d706870266c6f676f436f6c6f723d7768697465)](composer.json) [![Laravel](https://camo.githubusercontent.com/9f5bfd36130f0599995d7861cc4bb20c6c2ef58ef4a380f7ed013e103643fc5e/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c61726176656c2d3131253230253743253230313225323025374325323031332d4646324432303f6c6f676f3d6c61726176656c)](composer.json) [![PHPStan](https://camo.githubusercontent.com/1bc07920f0d36e55c17e1d38b1caa132cc605f51a82b388c962870b9a747b898/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5048505374616e2d6c6576656c253230392d627269676874677265656e2e737667)](phpstan.neon) [![Rector](https://camo.githubusercontent.com/9286512bc0762af8c37418ae625e9977502194b51f89609b24bcfef6e1ba5575/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f526563746f722d70617373696e672d627269676874677265656e2e737667)](rector.php) [![Code Style: Pint](https://camo.githubusercontent.com/7c8875633cb083fe4b31e4f2e2cb344b2ac42ebfa56ba5b2bf5f84f9cc4af64d/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f636f64652532307374796c652d4c61726176656c25323050696e742d4646324432302e7376673f6c6f676f3d6c61726176656c)](https://github.com/laravel/pint) [![License](https://camo.githubusercontent.com/8bb50fd2278f18fc326bf71f6e88ca8f884f72f179d3e555e20ed30157190d0d/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c6963656e73652d4d49542d677265656e2e737667)](LICENSE)

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 (eager or lazy with TTL), subtree cloning, JSON tree import/export, materialised-path columns, and an opinionated repair toolkit.

```
use App\Models\BudgetItem;

$root = new BudgetItem(['name' => 'Engineering']);
$root->saveAsRoot();

$child = new BudgetItem(['name' => 'Salaries', 'cost' => 26000]);
$child->appendToNode($root)->save();

$child->depth;                       // 1
$child->isLeaf();                    // true
$child->isDescendantOf($root);       // true
$child->parent;                      // $root  (Eloquent relation, eager-loadable)
$child->ancestors()->get();          // collection containing $root

$root->refresh();                    // re-read parent bounds after the append
$root->descendants()->get();         // collection containing $child
$root->getDescendantCount();         // 1  (descendants, excluding self; +1 for total nodes in subtree)
```

Declare aggregates on the model and the SUM / COUNT / AVG / MIN / MAX roll-ups are maintained automatically as the tree changes:

```
use Illuminate\Database\Eloquent\Model;
use Vusys\NestedSet\Attributes\NestedSetAggregate;
use Vusys\NestedSet\Contracts\MaintainsTreeAggregates;
use Vusys\NestedSet\Export\AsciiOptions;
use Vusys\NestedSet\NodeTrait;

#[NestedSetAggregate(column: 'cost_total',      sum:   'cost')]
#[NestedSetAggregate(column: 'item_count',      count: true)]
#[NestedSetAggregate(column: 'avg_cost',        avg:   'cost')]
#[NestedSetAggregate(column: 'biggest_item',    max:   'cost')]
#[NestedSetAggregate(column: 'recurring_total', sum:   'cost', filter: ['recurring' => true])]
class BudgetItem extends Model implements MaintainsTreeAggregates
{
    use NodeTrait;

    protected $fillable = ['name', 'cost', 'recurring'];   // so the mass-assignment below runs
}

// Render the forest with each node's own cost + rolled-up subtree total:
$render = fn () => BudgetItem::toAsciiTreeForest(new AsciiOptions(
    label: fn ($n) => "{$n->name}  (cost = {$n->cost}, total = {$n->cost_total})",
));

echo $render();
// Engineering              (cost = 0,     total = 32000)
// ├── People               (cost = 0,     total = 28000)
// │   ├── Salaries         (cost = 26000, total = 26000)
// │   └── Bonuses          (cost = 2000,  total = 2000)
// └── Tools                (cost = 0,     total = 4000)
//     ├── SaaS             (cost = 2500,  total = 2500)
//     └── Hardware         (cost = 1500,  total = 1500)
// Operations               (cost = 0,     total = 1500)
// └── Office               (cost = 1500,  total = 1500)

BudgetItem::query()->where('name', '=', 'Bonuses')->first()->update(['cost' => 4000]);
BudgetItem::query()->where('name', '=', 'Engineering')->first()->refresh()->cost_total;   // 34000  — every ancestor updates (Bonuses → People → Engineering)

// move the whole Tools subtree (3 nodes) under Operations — one statement
BudgetItem::query()->where('name', '=', 'Tools')->first()
    ->moveTo(BudgetItem::query()->where('name', '=', 'Operations')->first())
    ->save();
echo $render();
// Engineering              (cost = 0,     total = 30000)   ← old parent shrank (Tools left, taking 4000)
// └── People               (cost = 0,     total = 30000)
//     ├── Salaries         (cost = 26000, total = 26000)
//     └── Bonuses          (cost = 4000,  total = 4000)
// Operations               (cost = 0,     total = 5500)    ← new parent grew by the whole moved subtree
// ├── Office               (cost = 1500,  total = 1500)
// └── Tools                (cost = 0,     total = 4000)
//     ├── SaaS             (cost = 2500,  total = 2500)
//     └── Hardware         (cost = 1500,  total = 1500)

BudgetItem::query()->withFreshAggregates()->get();   // ad-hoc correlated recomputation (read-only — see Aggregates → Drift)
```

Why nested set?
---------------

[](#why-nested-set)

The 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.

Installation
------------

[](#installation)

```
composer require vusys/laravel-nestedset
```

The service provider auto-registers Blueprint macros and registers a publishable config file:

```
php artisan vendor:publish \
    --provider="Vusys\NestedSet\NestedSetServiceProvider" \
    --tag=nestedset-config
```

See the [Installation guide](https://vusys.github.io/laravel-nestedset/getting-started/installation.html) for the rest of the setup (migration macros, model trait, scoped trees).

Documentation
-------------

[](#documentation)

Full documentation lives at ****.

- **Getting Started** — [Introduction](https://vusys.github.io/laravel-nestedset/) · [Installation](https://vusys.github.io/laravel-nestedset/getting-started/installation.html) · [Migration](https://vusys.github.io/laravel-nestedset/getting-started/migration.html) · [Primary Keys](https://vusys.github.io/laravel-nestedset/getting-started/primary-keys.html) · [Model Setup](https://vusys.github.io/laravel-nestedset/getting-started/model-setup.html)
- **Tree Operations** — [Inserting &amp; Moving](https://vusys.github.io/laravel-nestedset/tree-operations/inserting.html) · [Reordering Siblings](https://vusys.github.io/laravel-nestedset/tree-operations/reordering.html) · [Soft Deletes](https://vusys.github.io/laravel-nestedset/tree-operations/soft-deletes.html) · [Bulk Insertion](https://vusys.github.io/laravel-nestedset/tree-operations/bulk-insertion.html) · [Cloning Subtrees](https://vusys.github.io/laravel-nestedset/tree-operations/cloning.html) · [Materialised Paths](https://vusys.github.io/laravel-nestedset/tree-operations/materialised-paths.html)
- **Querying** — [Tree Queries](https://vusys.github.io/laravel-nestedset/querying/queries.html) · [Eloquent Relations](https://vusys.github.io/laravel-nestedset/querying/relations.html) · [In-memory Tree Shaping](https://vusys.github.io/laravel-nestedset/querying/tree-shaping.html) · [Walking Subtrees](https://vusys.github.io/laravel-nestedset/querying/walking.html) · [Tree Exporters &amp; JSON Import](https://vusys.github.io/laravel-nestedset/querying/exporters.html) · [Tree Diff](https://vusys.github.io/laravel-nestedset/querying/tree-diff.html) · [Inspection](https://vusys.github.io/laravel-nestedset/querying/inspection.html) · [Scoped Trees](https://vusys.github.io/laravel-nestedset/querying/scoped-trees.html)
- **Aggregates** — [Overview](https://vusys.github.io/laravel-nestedset/aggregates/overview.html) · [Setup](https://vusys.github.io/laravel-nestedset/aggregates/setup.html) · [Reading](https://vusys.github.io/laravel-nestedset/aggregates/reading.html) · [Declaring](https://vusys.github.io/laravel-nestedset/aggregates/declaring.html) · [Filtered](https://vusys.github.io/laravel-nestedset/aggregates/filtered.html) · [Collection](https://vusys.github.io/laravel-nestedset/aggregates/text-and-json.html) · [Listeners](https://vusys.github.io/laravel-nestedset/aggregates/listeners.html) · [Variance &amp; Stddev](https://vusys.github.io/laravel-nestedset/aggregates/maths.html) · [Weighted Avg &amp; Booleans](https://vusys.github.io/laravel-nestedset/aggregates/weighted-avg-and-booleans.html) · [Means](https://vusys.github.io/laravel-nestedset/aggregates/means.html) · [Quantiles](https://vusys.github.io/laravel-nestedset/aggregates/quantiles.html) · [Top-K](https://vusys.github.io/laravel-nestedset/aggregates/top-k.html) · [Bitwise](https://vusys.github.io/laravel-nestedset/aggregates/bitwise.html) · [Lazy](https://vusys.github.io/laravel-nestedset/aggregates/lazy.html) · [Recipes](https://vusys.github.io/laravel-nestedset/aggregates/recipes.html) · [Maintenance](https://vusys.github.io/laravel-nestedset/aggregates/maintenance.html) · [Drift &amp; Limitations](https://vusys.github.io/laravel-nestedset/aggregates/drift.html)
- **Maintenance** — [Tree Repair](https://vusys.github.io/laravel-nestedset/maintenance/fix-tree.html) · [Repairing Aggregates](https://vusys.github.io/laravel-nestedset/maintenance/fix-aggregates.html) · [Corruption Reference](https://vusys.github.io/laravel-nestedset/maintenance/corruption.html)
- **Reference** — [Configuration](https://vusys.github.io/laravel-nestedset/reference/config.html) · [Testing Helpers](https://vusys.github.io/laravel-nestedset/reference/testing.html) · [Factory Tree Builder](https://vusys.github.io/laravel-nestedset/reference/factories.html) · [Transactions](https://vusys.github.io/laravel-nestedset/reference/transactions.html) · [Events](https://vusys.github.io/laravel-nestedset/reference/events.html) · [Production Notes](https://vusys.github.io/laravel-nestedset/reference/production.html) · [Glossary](https://vusys.github.io/laravel-nestedset/reference/glossary.html)
- **Internals** — [Architecture Overview](https://vusys.github.io/laravel-nestedset/internals/architecture.html)

The site is built from the markdown in [`docs/`](docs/) — if you spot an error, edit the source and open a PR.

Contributing
------------

[](#contributing)

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 + feature
```

All four must pass on CI before merge.

Changelog
---------

[](#changelog)

See [CHANGELOG.md](CHANGELOG.md) for the release history and the pre-1.0 backwards-compatibility breaks called out per version.

License
-------

[](#license)

MIT. See [LICENSE](LICENSE).

###  Health Score

47

—

FairBetter than 93% of packages

Maintenance97

Actively maintained with recent releases

Popularity18

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity55

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 94% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~2 days

Total

30

Last Release

14d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/4213522?v=4)[Bryan](/maintainers/Vusys)[@Vusys](https://github.com/Vusys)

---

Top Contributors

[![Vusys](https://avatars.githubusercontent.com/u/4213522?v=4)](https://github.com/Vusys "Vusys (266 commits)")[![dependabot[bot]](https://avatars.githubusercontent.com/in/29110?v=4)](https://github.com/dependabot[bot] "dependabot[bot] (17 commits)")

---

Tags

laraveleloquenttreehierarchyadjacency listnested-setaggregatesMPTTnested set model

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan, Rector

Code StyleLaravel Pint

### Embed Badge

![Health badge](/badges/vusys-laravel-nestedset/health.svg)

```
[![Health](https://phpackages.com/badges/vusys-laravel-nestedset/health.svg)](https://phpackages.com/packages/vusys-laravel-nestedset)
```

###  Alternatives

[psalm/plugin-laravel

Psalm plugin for Laravel

3345.3M347](/packages/psalm-plugin-laravel)[mongodb/laravel-mongodb

A MongoDB based Eloquent model and Query builder for Laravel

7.1k8.4M98](/packages/mongodb-laravel-mongodb)[watson/validating

Eloquent model validating trait.

9803.5M55](/packages/watson-validating)[baril/bonsai

An implementation of the Closure Tables pattern for Eloquent.

3596.2k](/packages/baril-bonsai)[typicms/nestablecollection

A Laravel Package that extends Collection to handle unlimited nested items following adjacency list model.

88337.7k26](/packages/typicms-nestablecollection)[aimeos/laravel-nestedset

Nested Set Model for Laravel

3714.4k7](/packages/aimeos-laravel-nestedset)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
