- How do I install and set up baril/orderly in a Laravel model?
- Install it with Composer (composer require baril/orderly) and, if you are not using package discovery, register Baril\Orderly\OrderlyServiceProvider in config/app.php. Add an unsignedInteger position column to the table, then use the Baril\Orderly\Concerns\Orderable trait in your model. Guard the position attribute (for example protected $guarded = ['position']) because it is managed by the package rather than filled manually.
- Can I use a different column name than position with Orderly?
- Yes. The default column is position, but you can set the protected $orderColumn property on your model to any column name you prefer, such as order or sort_order. You must then guard that column instead of position and make sure the migration creates it. No other configuration is required.
- Which Laravel versions does baril/orderly support?
- The package covers Laravel 6 through 13. Laravel 13 needs Orderly 3.4+, Laravel 12 needs 3.3+, Laravel 11 needs 3.2+, Laravel 10 needs 3.1+, and Laravel 9 works with the 3.x line. Laravel 7 and 6 use 1.x, while Laravel 8 can use either 2.x or 3.x, so check the compatibility table before upgrading a major version.
- How does moveToOffset work for reordering records?
- Call moveToOffset($offset) on a model to change its position, where offsets start at 0 and negative values count from the end, so -1 means last place. The package also provides other relative move helpers, and you do not need to call save() afterwards. This makes it straightforward to implement drag-and-drop or up/down controls in an admin panel.
- Does Orderly maintain positions automatically when records are created or deleted?
- Yes. New records are appended at the end automatically, and deleting a record closes the gap in the sequence, so you never have to renumber manually. The catch is that bulk operations such as Model::query()->delete(), raw SQL, imports and seeders bypass model events and can leave gaps. The package ships an orderly:fix-positions command to repair those situations.
- Can I order records within groups, like per tenant or per section?
- Yes. Orderly supports a group scope through the $groupColumn property, and composite columns are supported, which covers tenant-scoped or section-scoped ordering without extra work. Each group maintains its own independent position sequence. This keeps a single table usable for multiple ordered lists, such as a CMS with separate content sections.
- How do I reorder a whole list in bulk without an N+1 query problem?
- Use the OrderableCollection bulk path: saveOrder() and setOrder() let you persist a new ordering in one operation instead of saving each model individually. This avoids the classic N+1 reorder bug that shows up in hand-rolled implementations. It is the main reason the package is worth using over a custom sort_order column with a loop.
- Does Orderly support ordering on many-to-many and polymorphic relationships?
- Yes. The belongsToManyOrderable and morphToManyOrderable relationship variants keep positions correct through sync, attach and detach. That covers common cases like tags, media galleries and featured items on a pivot table. Pivot ordering is where in-house implementations usually break down, so this is a significant part of the package's value.
- Is baril/orderly safe to use in production with concurrent writes?
- Position assignment on create and relative moves are read-then-write sequences, and the README does not document locking or unique-constraint guidance, so concurrent inserts or simultaneous drag-and-drop saves can interleave. Moves are also O(n) in the affected scope, so very large lists need a different approach. These are not disqualifying, but you should make an explicit decision on transactions, locking and whether a unique index on the group and position columns is appropriate for your workload.
- Is baril/orderly actively maintained, and what are the adoption risks?
- The project has a small adoption signal, with a single maintainer and few dependents, so you may be among the first production users and would absorb the cost of discovering edge cases. Mitigating factors are an active test suite with published coverage, a release cadence that tracks Laravel majors from 6 to 12, and a 3.3.x line that broadened driver support to SQLite, PostgreSQL and SQL Server. It is a leaf dependency with no service container footprint, config file or migrations of its own, which keeps the exit cost low if you need to replace it.