runroom-packages/sortable-behavior-bundle
Runroom Sortable Behavior Bundle adds easy sortable behavior to Symfony and Doctrine entities. Use a position field and trait to make records reorderable, then manage ordering in your admin or custom UI. Great for categories, menus, and any list that needs drag-and-drop sorting.
Framing correction (material to the decision): this is a Symfony bundle, not a Laravel package. It extends Sonata Admin list views with drag-and-drop ordering, backed by a Doctrine sortable behavior (Gedmo/Stof-style position column). The brief's "Laravel/PHP package" framing is inaccurate and changes the verdict — see Integration Approach.
Architecture fit. Zero for a Laravel codebase. The package depends on extension points Laravel does not have: a Symfony bundle kernel and service container, Twig templates, Sonata Admin's list-block/route/batch-action model, and Doctrine ORM entities with a registered sortable event subscriber. There is no adapter path; you would be reimplementing the feature, not integrating the package. Fit is conditional-but-plausible only where Sonata Admin and Doctrine ORM are already load-bearing.
Integration feasibility. Even in a Symfony context this is not a drop-in. It presumes an existing Sonata Admin investment (a large, opinionated, slow-moving admin layer), a Doctrine sortable listener already wired, and an asset pipeline capable of serving the drag-drop JS. Composer constraints against our Symfony/PHP/Sonata versions must be verified before any estimate — small helper bundles in this ecosystem routinely lag major Symfony releases.
Technical risk. High, driven almost entirely by maintenance signals rather than code quality: 11 stars, 0 dependents, and a [READ-ONLY] repo name strongly suggesting a subtree split of the Runroom monorepo — meaning issues and PRs route to the parent project, and releases arrive only when that monorepo tags. There is no observable security or support stream for the split itself. Mitigating factor: the surface area is small glue code, so the blast radius of abandonment is bounded and the MIT license makes vendoring/forking cheap. The realistic risk is not "it breaks tomorrow" but "nobody tells us when it breaks."
Key questions.
composer.json constraints (Symfony, PHP, Sonata Admin, Doctrine sortable)? Do they intersect our supported matrix?Stack fit. Three cases:
spatie/laravel-eloquent-sortable plus a Filament/Nova/Livewire drag-drop, or a hand-rolled position column using fractional/LexoRank-style keys. Do not spend discovery time on this package.Migration path. There is no migration; this is a greenfield admin-UX feature. Adopt it for new sortable lists only. Do not retrofit it onto existing admin screens as part of an unrelated upgrade — that couples two risk surfaces.
Compatibility. Pin explicitly and verify in the spike: Symfony major, PHP minor, Sonata Admin version, and the underlying Doctrine sortable behavior version. Expect to pin rather than float. Confirm the JS asset story works with our build pipeline before committing.
Sequencing.
composer require the split repo vs. vendor the source into our tree under MIT. Given the maintenance signals, I lean to vendoring with a documented upstream commit so a Symfony upgrade can't strand us.Maintenance. If adopted, we own it. A read-only split means upgrades arrive on the parent project's schedule, not ours, and only if Runroom happens to tag. Budget for a named internal maintainer, a recorded fork point, and an upgrade runbook. The MIT license makes internalization frictionless — treat that as the default posture, not the fallback.
Support. No vendor, no SLA, and community support is effectively nil at 11 stars and 0 dependents. Any question we have, we answer ourselves. This should be stated plainly to stakeholders rather than buried.
Scaling. This is the substantive technical concern. Positional sortable behavior reindexes siblings on every move (UPDATE ... SET position = position ± 1 WHERE ...), which is O(n) write amplification per drag. Acceptable for admin lists in the hundreds; poor for large lists or frequently reordered ones — row-lock contention, deadlock risk on concurrent drags, and duplicate or gapped position values when two admins reorder simultaneously. Mitigations: wrap moves in a transaction with explicit locking, cap list size, or replace positional integers with sparse/fractional ordering. Also note the UX trap: Sonata lists are paginated, so cross-page drag ordering is easy to mis-specify and hard to test.
Failure modes. Duplicate or gapped positions after concurrent edits; silent no-op when the sortable listener isn't registered (drag persists nothing, no error); orphaned JS after an asset-pipeline change; bundle registration breakage on a Symfony major upgrade; and the whole dependency blocking a PHP minor upgrade with no upstream fix available.
Ramp-up. Code volume is low, so the package itself is learnable in an afternoon. The real cost is Sonata Admin fluency — a specialized and shrinking skill set. Days for a developer new to Sonata, near-zero for one who knows it, and "learn a second framework" for a Laravel-first team, which is a hard no.
Recommendation: treat as not applicable for a Laravel stack; for an existing Symfony + Sonata estate, permit a time-boxed spike and default to vendoring under MIT with named internal ownership. Do not adopt as an unowned composer require dependency.
How can I help you explore Laravel packages today?