tadcka/tree
tadcka/tree is a PHP package for managing hierarchical tree structures, with support for defining nodes, parent-child relationships, traversal, and nested data organization. It helps integrate reusable tree logic into Laravel or plain PHP applications.
Before you write a line of code, confirm what you actually have. tadcka/tree has a last release of February 2017, zero dependents, and zero stars. The description references Laravel/Eloquent integration, but this package originates from the Symfony 2 / Tadcka CMS ecosystem. Clone the repo and read composer.json and src/ first — do not assume the Eloquent API described in the blurb exists as written.
Minimal path:
Install and inspect.
composer require tadcka/tree
If the constraint fails on your PHP version (likely on PHP 8+), vendor it as a path repository or fork it — you will almost certainly need to patch type hints and return types for modern PHP.
Read these first, in order:
composer.json — supported PHP range, autoload namespace, dependencies (this tells you whether it is Symfony- or Eloquent-oriented).src/ — these define what your domain entity must implement.First use case: a menu or category tree. Create one root node, add two children, then query descendants. This exercises the full write → read path and will surface integration problems early (missing interface methods, incompatible parent type hints, autoloading).
Decide your storage strategy before modelling. The package predates modern Laravel tree packages, so confirm whether it expects an adjacency list (parent_id), a materialized path, or a nested set. Your migrations depend entirely on this — get it wrong and every subsequent move() will corrupt your tree.
If step 1–3 reveals that the Eloquent claims are aspirational, plan for a thin adapter layer between your Eloquent model and the package's interfaces rather than trying to make Eloquent itself satisfy them.
Adapter over inheritance. The safest pattern for a 2017 package in a modern Laravel app is a wrapper: your Eloquent model stays clean, and a small adapter class implements the package's node contract by delegating to $model->parent_id, $model->children(), etc. This keeps the abandonment risk contained to one file.
class NodeAdapter implements TreeNodeInterface
{
public function __construct(private Category $model) {}
public function getParent(): ?self
{
return $this->model->parent
? new self($this->model->parent)
: null;
}
public function getChildren(): iterable
{
return $this->model->children->map(fn ($c) => new self($c));
}
}
Repository-shaped manager usage. If the package ships a tree manager, register it as a singleton in a service provider and inject it — do not instantiate it per call. Tree managers frequently cache the root or current node, and scattered instantiation leads to stale reads inside a single request.
Wrap every mutation in a transaction. Insert, move, and delete potentially touch multiple rows when maintaining path/depth columns:
DB::transaction(function () use ($manager, $node, $target) {
$manager->move($node, $target); // or moveBefore/moveAfter
});
Eager-load for traversal. Recursive accessors will trigger N+1 queries. If you control the query, load the whole subtree in one go and traverse in memory:
$flat = Category::whereDescendantOf($root)->get(); // or your own closure-table/recursive CTE
$tree = $flat->toTree(); // build hierarchy in PHP
Build nested-list rendering from depth/path data, not recursion. If the package exposes depth or path, a single ordered query plus str_repeat(' ', $depth) is dramatically cheaper than recursive relationship loading for menu output.
Integration tips:
before/after insertion semantics, confirm the ordering column is unique-scoped to siblings; otherwise concurrent inserts produce ties.The documentation/description does not match the package. The blurb promises Laravel/Eloquent integration and sibling/depth/path helpers. The repository is a Symfony-era component with no Laravel service provider. Treat the description as aspirational marketing, verify every method against src/, and budget time for writing your own Eloquent glue.
Abandonment is the headline risk. Last release 2017, zero stars, zero dependents means:
implicit nullable deprecations, missing : void/: static return types, and possibly each()/create_function() in helpers."repositories": [{"type": "vcs", ...}].Mutation is the dangerous surface. Move and delete are where trees corrupt. Test explicitly:
Debugging tips:
parent_id/path data is inconsistent. Rebuild from a known-good source rather than patching.Config quirks to check:
parent_id, position, path, depth) are often hard-coded in the package. If your schema differs, you may need to alias in SQL or fork.use Tadcka\Tree\... works.Extension points to prefer:
kalnoy/nestedset, staudenmeir/laravel-adjacency-list, or baum later without touching domain code. Given the package's status, plan the exit before you start.Bottom line: viable as a learning reference or an internal, forked-and-patched dependency for an existing legacy app. For a new Laravel project, the maintenance cost almost certainly exceeds the benefit of picking it over a maintained tree package — but the interface-driven adapter pattern above lets you try it without betting the codebase on it.
How can I help you explore Laravel packages today?