Product Decisions This Supports
- Hierarchy data modeling (the core decision). This package implements a closure-table/"common table" approach to recursive relationships: ancestor–descendant pairs are stored in a single table, so "all descendants of X" or "is A an ancestor of B" become flat indexed queries instead of recursive application-level loops. Adopting it is really a decision to commit to a closure table as the storage model for at least one domain object.
- Feature scoping with depth-aware queries. Unlocks features that are expensive to bolt on later: unlimited-depth category navigation and breadcrumbs, "include all sub-categories" filtering in search/listing, inherited permissions/roles, subtree-scoped reporting, threaded comments/replies, org-chart or territory roll-ups, referral/partner tree views.
- Build vs. buy (vs. fork). At 27 stars, a single 2020 release, and zero dependents, this is a reference implementation, not a supported dependency. The realistic PM framing is "buy a two-day spike, then decide between vendoring/forking it or writing ~300–500 lines of closure-table logic ourselves." Either way the estimate is small; the risk is in invariant correctness, not code volume.
- Roadmap sequencing. If hierarchy depth is a v2 concern, this decision can be deferred — but the schema choice (adjacency list
parent_id vs. closure table) is hard to reverse once data and queries exist. Use this package as the forcing function to lock that schema decision now, even if adoption waits.
- Make/buy signal on maintenance. Zero dependents + last release 2020-12-17 means our Composer constraints likely need to be widened or patched to run on current Laravel. That cost belongs in the build-vs-buy math, not discovered mid-sprint.
- Use-case prioritization. Best fit where reads dominate and depth is unbounded or unknown (CMS page trees, product taxonomies, multi-level partner/referral structures). Poor fit for shallow, fixed-depth hierarchies (region → country → city), where a plain
parent_id plus one join is cheaper and simpler.
When to Consider This Package
Consider it when:
- The domain genuinely needs both ancestor and descendant traversal at arbitrary depth, on a read-heavy path (navigation, filters, permission checks).
- You're on (or can pin to) the Laravel/PHP versions its Composer constraints actually support — verify this explicitly before assuming compatibility; the 2020 release predates several major Laravel versions.
- You accept the maintenance posture: MIT license, forkable, small enough to audit and own. Plan a vendor/fork with our own test suite covering the invariants — no cycles, correct depth values, correct pair insertion on create, correct pair pruning on delete, correct subtree re-write on move.
- You want a working reference for the closure-table pattern to de-risk a short technical spike rather than a long design cycle.
Look elsewhere when:
- You need a supported dependency with a maintenance commitment, security patching, or a vendor to escalate to. This fails that bar; 27 stars / 0 dependents / one 2020 release is a clear signal.
- Your database can do this natively and cheaply: MySQL 8+ / PostgreSQL recursive CTEs, or
ltree/ltree-style path types, cover most "moderate depth, moderate traffic" needs without a denormalized table.
- Writes, moves, and re-parenting are frequent or user-facing — closure tables pay O(depth) per insert and per subtree move, and every move is a multi-row transaction with invariant risk.
- Established alternatives fit better:
kalnoy/nestedset (nested set — fast reads, slower writes, good for mostly-static trees), staudenmeir/laravel-adjacency-list (recursive CTEs over your existing parent_id, actively maintained), tightenco/parental, or an in-house closure table. Prefer any of these over an unmaintained micro-package unless the spike proves it's a clean fit.
- The tree is shallow and fixed-depth — a
parent_id column and one or two joins is the right answer; don't buy complexity you don't need.
- Multi-tenancy, soft deletes, or polymorphic ownership are in scope — validate these interactions specifically; small packages in this space often don't cover them, and the gaps surface as data corruption, not errors.
How to Pitch It (Stakeholders)
To executives: This is a small open-source library (MIT, ~27 GitHub stars, last released December 2020, no downstream dependents) that makes hierarchical data — category trees, org structures, permission inheritance, partner/referral trees — cheap to query. It is not a vendor product: no support contract, no active maintenance. The recommendation is a timeboxed spike (1–2 days) to validate it against our Laravel version, then either vendor/fork it under our own tests or replace it with a short in-house implementation using the same pattern. Cost either way is days, not weeks; the value is avoiding a schema decision we'd have to unwind later. Do not adopt it as an unqualified dependency on a revenue-critical path.
To engineering: It's a closure-table implementation for Eloquent — a "common table" of ancestor/descendant pairs with depth, giving constant-ish read cost for descendant/ancestor queries at the price of write amplification on insert, delete, and re-parent. Treat it as a design reference first. Before adopting, (1) confirm Composer/PHP/Laravel constraints against our stack, (2) write invariant tests for cycle prevention, depth bookkeeping, and subtree moves, (3) benchmark write-heavy paths, and (4) compare against staudenmeir/laravel-adjacency-list on recursive CTEs and against kalnoy/nestedset if our trees are mostly static. If we proceed, we own the code — vendor it, pin it, and document the fork.