mikeevstropov/sortable-tree-bundle
Symfony bundle for building sortable, hierarchical trees from Doctrine entities. It provides tree management, reordering, and nested-set support for nested menus, categories, and other ordered structures with minimal configuration.
What this package actually is: Despite being routed through a PHP package feed, mikeevstropov/sortable-tree-bundle is a Symfony 2/3 bundle, not a Laravel package. It ships a Symfony Bundle class, DI extension, YAML/XML service configuration, Twig templates, and (almost certainly) Doctrine-based tree handling with a drag-and-drop front end for admin listings. Its stated purpose — "sortable feature for your Symfony2/3 admin tree listing" — implies coupling to a specific admin layer (Sonata Admin, ONGR, or a bespoke one) and to Doctrine tree semantics (nested set or adjacency).
Architecture fit: Effectively zero at the artifact level. Our stack is Laravel/Eloquent/Blade with a Laravel-native admin surface. None of the bundle's four core seams — Symfony DI container, Doctrine ORM, Twig, Symfony event dispatcher — exist in our runtime without bridging layers we would have to write and own. The domain concept is a legitimate fit: hierarchical records with stable, user-controlled ordering in an admin screen is a recurring requirement, and we will likely need it again.
Integration feasibility: composer require will not produce a working installation. Expect constraint conflicts on php (5.3/5.x-era constraint), symfony/symfony (~2.3–3.x), and doctrine/orm. Even if coerced in with --ignore-platform-reqs, there is no service provider, no Blade view, no Eloquent driver, and no Laravel controller surface. Realistic paths:
| Path | Effort | Verdict |
|---|---|---|
| Install as a dependency | Not achievable | Reject |
| Fork and port to Laravel | 8–15 engineer-days, forever-owned | Reject |
| Read as a spec/UX reference, rebuild on maintained libs | 2–4 engineer-days | Recommended |
Technical risk (high, concentrated):
Key questions to close before any decision: What tree strategy does it implement (nested set vs adjacency vs materialized path), and does it rebalance transactionally? What admin bundle does it bind to, and does that constrain the port? What is the license and is the author reachable for a security contact? Which files carry the reorder endpoint, and does it enforce CSRF and per-record authorization? Is the sorting behavior per-tree-scope (tenant-safe) or global? What is the actual end-to-end flow the current users rely on — is it reorder-within-parent, move-across-parents, or both?
Stack fit: Treat the package as a reference implementation, not a component. Map its concepts onto Laravel-native primitives rather than bridging Symfony into Laravel:
| Bundle concern | Laravel equivalent |
|---|---|
| Symfony Bundle + DI extension | Service provider + config/*.php |
| Doctrine nested set | kalnoy/nestedset or staudenmeir/laravel-adjacency-list (Eloquent) |
| Twig listing template | Blade component |
| Symfony EventDispatcher hooks | Laravel events/listeners |
| jQuery UI Sortable | SortableJS (maintained, framework-agnostic) |
| Symfony AJAX reorder route | Laravel controller + FormRequest + policy |
Migration path: No data migration is implied because nothing is in production on our side — this is greenfield adoption of a pattern. If we ever inherit a system running it, the migration is a data-shape migration (lft/rgt or parent/position columns into our chosen Eloquent tree library), not a code migration. Extract the behavior from the package (endpoint contract, ordering semantics, edge cases like moving a node to root) and write it as an internal spec before writing code.
Compatibility: Assume incompatible by default and verify only if someone insists: composer why-not against our Laravel/PHP matrix will be the decisive, one-hour check. Do not spend more than that; the archived status already dominates the decision.
Sequencing (recommended 3-sprint slice):
PATCH /admin/{resource}/reorder with FormRequest validation of node IDs, policy check on the parent scope, CSRF, idempotency key.Maintenance: Zero upstream maintenance — we inherit 100% of the burden for anything we fork, including PHP 8.x compatibility, security patches, and dependency drift. Archiving also means no issue triage, no PR review, and no release cadence to align with. A fork becomes a permanent line item in our dependency inventory with no exit ramp other than rewrite.
Support: Single-author, dormant project with no community around it. There is no realistic escalation path for a production incident, and no CVE feed will cover it — vulnerability discovery would be entirely internal. Any usage must be paired with a documented "we own this" entry in our third-party risk register.
Scaling: Tree reordering is a write-amplification pattern: nested-set moves touch O(n) rows per operation, and concurrent reorders on the same parent can interleave into inconsistent bounds. At admin-scale volumes (tens to low hundreds of nodes per tree, a handful of editors) this is fine; at high editor concurrency or very deep trees it needs serialization (queue or per-tree advisory lock) and a repair job. Read paths are cheap if we avoid N+1 on the listing query.
Failure modes to design against: partial reorder when the AJAX call fails mid-tree (requires transactional write + client rollback); corrupted lft/rgt bounds from an interrupted operation (requires a tree:fix command and a health check); cross-tenant bleed if ordering scope is not constrained to the parent/tenant; missing authorization on the reorder endpoint (a classic IDOR on drag-and-drop APIs); two editors fighting over the same subtree producing silent reordering of each other's work.
Ramp-up: The package itself teaches nothing current — an engineer reading it learns Symfony 2 conventions they cannot reuse. The real ramp-up cost is the tree data structure: roughly one day for a mid-level engineer to become productive with nested-set semantics (bounds, subtree moves, why lft/rgt shift) and half a day for the front-end integration. Budget 1.5 days of onboarding against the rebuild, versus an open-ended and unquantifiable cost against a fork.
Bottom line for the roadmap: Do not adopt. Record the capability gap, fund the 2–4 day Laravel-native rebuild using a maintained tree library, and keep this repository only as a behavioral reference during spec writing.
How can I help you explore Laravel packages today?