james.xue/laravel-sortable
Laravel Sortable adds easy drag-and-drop ordering to Eloquent models: define sortable columns, automatically manage positions on create/update/delete, and reorder records with simple query helpers. Ideal for menus, galleries, and any list that needs custom sequencing.
Architecture fit. This is a single-concern Eloquent behavior package: a trait that maintains a positional column on a model and exposes reordering operations. That shape is architecturally clean — it lives entirely at the persistence layer, has no service-provider-heavy bootstrapping, and imposes no opinion on controllers, APIs, or UI. It is a natural fit anywhere an application models an ordered collection: CMS navigation, category trees, FAQ/banner ordering, ordered lookup tables, workflow step sequences. Because the contract is a trait plus a column, it also composes well with repository/service patterns and does not leak into domain logic.
Integration feasibility. Mechanically trivial: composer require, a migration adding a positional column, and a use statement on the target model. The real feasibility question is not "can we wire it in" but "can we trust it." With 2 stars and 0 dependents, there is effectively no production evidence. Before adoption, a TPM should require a source read of the trait — the entire behavior likely fits in one or two files — plus verification of composer.json constraints against the team's Laravel and PHP versions. A package this small is often faster to audit than to evaluate.
Technical risk. Three risks dominate:
Key questions to resolve before commitment.
orderBy position partitioned by parent_id / tenant_id), or only a global sequence?creating/deleting/restoring hooks registered, and do they behave correctly with soft deletes?illuminate/* and PHP version constraints, and is there a test suite?spatie/eloquent-sortable, the de facto standard with orders-of-magnitude more adoption?Stack fit. Framework-agnostic within Laravel: it depends only on Eloquent, so it slots into monoliths, modular monoliths, and API-only services alike. No frontend or queue assumptions. This makes it a low-blast-radius addition — reversible by dropping the trait and column.
Migration path. Treat it as a schema-plus-behavior change, not a library install:
(scope_columns, position) if scoping is supported).UPDATE/batch job, inside a transaction.order column, run a dual-write window where both old and new columns are maintained, then cut reads over, then drop the old column.Compatibility. Verify the illuminate/support constraint line actually covers the target Laravel major (packages of this vintage frequently cap at older versions). Confirm PHP version parity with CI. Check for collisions with any existing model observers, global scopes, or a competing sortable package already in the dependency tree — two traits both writing a position column will corrupt data silently. Also confirm behavior with withoutEvents() bulk inserts, seeders, and factories, which bypass model events and will not populate positions.
Sequencing.
spatie/eloquent-sortable on scoping, concurrency, and bulk reorder (0.5 day).Given the adoption signal, the default recommendation for most teams will be fork or reimplement rather than depend — the package is small enough that ownership cost is low and supply-chain risk drops to zero.
Maintenance. This is the dominant operational concern. A single-maintainer package with 2 stars should be assumed unmaintained. Pin the exact version, vendor the source into the repo or an internal Composer registry, and assign a named internal owner. Budget a recurring line item for compatibility patches on each Laravel major upgrade.
Support. There is no meaningful community to escalate to. All support is internal: the team owning the model owns the behavior. Document the consumed API surface (trait methods, column name, event hooks) so a future engineer can replace the package without archaeology.
Scaling. The failure mode to watch is reorder cost as list size grows. Full-set reindexing is fine for dozens of rows and pathological for tens of thousands — it serializes writes and holds locks. If any target list can plausibly exceed a few hundred items, require a gap/fractional-position strategy or batch reindexing in a queued job. Also consider read amplification: every ordered query now sorts on the position column, so the index matters.
Failure modes to monitor.
Instrument with a periodic integrity check (duplicate-position and gap queries) and alert on reorder latency.
Ramp-up. The API surface is tiny, so a mid-level engineer can be productive in under a day — but only by reading source, since documentation is likely minimal. Plan for 1–2 days of onboarding that includes writing the missing tests (position assignment on create, reorder, delete, concurrent move, scoped ordering) as a condition of adoption. Those tests are also the artifact that makes a future fork or replacement safe.
How can I help you explore Laravel packages today?