staudenmeir/laravel-adjacency-list
Laravel Eloquent extension that adds recursive relationships for tree and graph structures using common table expressions (CTEs). Traverse categories, page hierarchies, nested comments, and more across MySQL, PostgreSQL, SQLite, SQL Server, and MariaDB.
parent_id adjacency list. This removes the usual pressure to adopt nested sets or closure tables just to avoid N+1 recursion. That means no extra tables, no maintained path/left-right indexes, no migration churn — a direct reduction in schema complexity and long-term maintenance cost.withCount('recursivePosts')), which often appear as follow-on requests.depth, path, and custom path columns plus toTree() nested serialization. That directly informs API contract decisions — you can offer "give me the subtree, nested, 3 levels deep" as a single endpoint instead of client-side assembly.withMaxDepth() lets you cap query cost at the product level ("show 3 levels, then lazy-load"), withQueryConstraint() supports business rules like "skip inactive users and their descendants," and cycle detection defines whether user-editable hierarchies are safe to ship without a data-integrity review.Adopt when:
parent_id-style schemas rather than introduce closure tables or nested sets.hasManyOfDescendants, belongsToManyOfDescendants, morphToManyOfDescendants) — e.g., "all posts by a user and everyone under them."Look elsewhere when:
Adoption checklist before committing:
withMaxDepth() defaults so no endpoint can traverse unbounded.For executives (one paragraph): We can deliver the hierarchy features already on the roadmap — nested categories, org structures, comment threads, inherited permissions, referral trees — for a fraction of the estimated effort, using a free, MIT-licensed, actively maintained open-source library that plugs into our existing Laravel codebase. It requires no new infrastructure, no schema redesign beyond the parent reference we already use, and no vendor contract. The primary risks are a database version prerequisite and the usual cost of adding a dependency, both of which we can retire in a contained refactor if needed.
For engineering leadership:
parent_id column you already have.withMaxDepth() for cost caps, withQueryConstraint() / withInitialQueryConstraint() / withRecursiveQueryConstraint() for business filtering, and configurable cycle detection with an is_cycle flag.For the product team:
path / custom paths like slug_path), "show all descendants," "count everything under this node," and subtree-wide bulk actions like deactivate or delete.Known risks to state plainly:
How can I help you explore Laravel packages today?