- What is lunarphp/nestedset and why does a separate nested set package exist?
- It is a Laravel package for storing and querying hierarchical data such as categories, menus, and org structures using the nested set model, with left and right indexes for fast ancestry and descendant lookups. It is a hard fork of kalnoy/nestedset, the de facto nested set implementation for Laravel, rebranded and re-namespaced under the Lunar organisation. The 1.0.0 release is a stabilisation release rather than a feature release: namespace rebrand, native type declarations, static analysis, a Testbench-based test suite, multi-engine CI, a global-scope hardening fix, and a zero-offset SQL fix. In practice it exists so the Lunar commerce stack can control its own tree implementation.
- How do I install lunarphp/nestedset in a Laravel application?
- Adoption is a Composer require of lunarphp/nestedset, importing the provided NodeTrait on your model, and a schema change that adds the nested set columns to the table. The package registers a Laravel service provider, so no manual bootstrapping is needed. This is low friction for a greenfield Laravel 12 project or anything inside the Lunar commerce stack. Pin the version constraint explicitly, since this is a young fork.
- Which Laravel versions does lunarphp/nestedset support?
- The package targets modern Laravel, with the compatibility claim pointing at Laravel 12 and 13. The Laravel version floor means it is a poor fit as a drop-in for a working kalnoy/nestedset 6.x installation on Laravel 10 or 11. Treat the Laravel 13 part of the constraint as forward-looking until you confirm it is actually exercised in CI. Check the composer.json constraint and the CI matrix before committing to an upgrade path.
- Can I swap lunarphp/nestedset in for kalnoy/nestedset in an existing project?
- No, it is not a drop-in replacement. The namespace rebrand touches every use statement, trait import, config publish tag, and any subclassed node behaviour in your codebase, so migration is an edit-everywhere task rather than a Composer swap. On top of that, adding native parameter and return types to trait methods is a subtle backward compatibility break for downstream subclasses and overrides written against the untyped upstream signatures, and it typically surfaces at runtime rather than at install time. Plan a real migration with tree integrity tests, not a constraint bump.
- What database columns does the nested set implementation require?
- You add _lft, _rgt, and parent_id columns to the table holding your tree, plus the appropriate indexes for the left and right values. The package creates nothing automatically, so the schema change is part of your migrations. Keep the columns consistent across every model that uses the trait, since tree integrity depends on them. After migrating existing data, rebuild the tree structure and verify the left and right values.
- How do I query ancestors and descendants efficiently?
- Nested sets answer ancestry and subtree questions with simple range comparisons on the left and right indexes, which is why they suit read-heavy hierarchies such as category trees, menus, and taxonomies. Fetching a full subtree or a node's ancestor chain is a single indexed query rather than a recursive walk. The trade-off is that writes are comparatively expensive, because inserting or moving a node shifts the indexes of its siblings and neighbours. Use this model when depth-first traversal and subtree reads dominate your workload.
- How do I move or reorder nodes in the tree?
- Node moves and reordering are handled through the trait's tree manipulation methods, which rewrite the left and right indexes to keep the structure valid. Because each move touches multiple rows, batch your reordering operations where possible and run them inside a transaction. If your node model has global scopes such as soft deletes, tenancy, or published status, confirm the scope behaviour during moves rather than assuming it. Re-run tree integrity checks after any bulk restructuring.
- Will global scopes or soft deletes break tree queries with this package?
- The 1.0.0 release includes a global-scope hardening fix, which is almost certainly a behavioural change: tree operations that previously inherited or ignored a global scope may now do the opposite. If your node model uses soft deletes, tenancy scopes, or published and active scopes, assume your query results may shift after upgrading. Re-run your tree integrity tests and any assertions that depend on scoped results. This is the kind of change that does not fail at install time, so test explicitly.
- Is lunarphp/nestedset production-ready, and how is it maintained?
- Technically the algorithm is proven, since it descends from the widely used kalnoy/nestedset implementation, and the fork adds static analysis, a Testbench-based suite, and multi-engine CI. The real risk is supply chain: this is a fork with a single primary contributor, and there is no stated upstream-sync policy, so upstream fixes, security patches, and future Laravel compatibility work have to be re-applied manually. There is also no documented security disclosure process in the release notes. If you adopt it, pin the constraint, watch upstream, and ask the maintainers about coverage of tree-mutating operations across MySQL, Postgres, and SQLite.
- What are the alternatives to lunarphp/nestedset and when should I avoid nested sets?
- The obvious alternative is staying on kalnoy/nestedset, which makes sense if you already have a working 6.x installation on Laravel 10 or 11 and no other reason to migrate. For write-heavy hierarchies, a plain parent_id adjacency list or recursive common table expressions may be a better fit, since nested set writes rewrite index ranges. For read-heavy category trees, menus, and taxonomies, nested sets remain a sound model. Choose based on your read-to-write ratio, not on the fork itself.