Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Column Sortable Laravel Package

kyslik/column-sortable

kyslik/column-sortable adds easy column sorting to Laravel 5.5–8 apps. Use Blade helpers to generate sortable links, configure sortable columns, and sort by related hasOne/belongsTo fields, with override and alias options for custom queries.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit. kyslik/column-sortable is a thin, opinionated convenience layer over Eloquent's query builder. It ships three things: a Sortable trait that adds a sortable() scope to models, a @sortablelink Blade directive, and a small config file. It does not introduce a service contract, repository abstraction, or middleware — it composes with paginate(), withCount(), and select() rather than replacing them. For a Blade-rendered Laravel monolith or admin panel, this is a near-perfect architectural fit. For an API-first or Inertia/Livewire front end where sorting is driven by client-side table state, the Blade directive (roughly half the package's value) is dead weight and you are effectively adopting a trait for building ORDER BY clauses.

Integration feasibility. Low effort in the happy path: composer require kyslik/column-sortable:^8.0, auto-discovery registers the provider, publish config, add use Sortable plus a $sortable array to the model, call ->sortable() in the controller. Advanced needs — relation sorting via dot notation (detail.phone_number), aliasing via $sortableAs, and join overrides via a {column}Sortable($query, $direction) method — are documented with working examples and a separate demo repository. A single developer can pilot this on one index page in under a day.

Technical risk. The dominant risk is not code quality but stewardship and documentation drift. Release notes show version 8.0.0 adding "Laravel 13.x Compatibility" contributed by the laravel-shift bot, while the README still advertises "Laravel 5.5-8" and the package description says "Laravel 6.x" — three conflicting compatibility statements in the same artifact set. Version history is a sequence of bot/bot-adjacent compatibility PRs (Laravel 9, 10, 11, 13), which means framework support is maintained reactively rather than designed. The reported zero dependents, against 644 stars, is a signal worth resolving before relying on the package: either the metric is a measurement artifact or real-world adoption is thinner than the star count implies. Security posture is reasonable — the $sortable whitelist is the injection boundary — but the fallback path to Schema::hasColumn() when $sortable is undefined inverts that: it queries the schema and infers allowed columns, which is both a per-request DB hit and a weaker contract. There is no multi-column sort, no stable sort tiebreaker, and relation sorting explicitly does not support combining two different relations in one request.

Key questions.

  1. Which Laravel versions are actually in scope, and does the 8.0.0 release line genuinely support them (README says 5.5–8, releases say up to 13)? We should verify against our exact laravel/framework constraint in CI before committing.
  2. Is our sort surface model-attribute-only, or do we need relation and aliased (withCount) sorting? The latter materially increases integration and test scope.
  3. What is the real dependency/usage signal? Zero dependents on a 644-star package needs an explanation before we treat it as a de facto standard.
  4. Is sorting a user-facing, user-controlled input in our product? If so, the whitelist discipline and ColumnSortableException handling (codes 0/1/2) become a security requirement, not a nicety.
  5. Given the scope, is build-versus-buy even a question? A sortable() scope with a whitelist is ~50 lines; the package's value is the Blade directive and relation conventions.

Integration Approach

Stack fit. Target the 8.0.0 line only if we are on a currently supported Laravel (11/12/13); on Laravel 10 pin ^6.5, on 9 pin ^6.4.2. Pin explicitly — the major version has tracked Laravel majors historically, so an unpinned constraint is how a routine composer update becomes an unplanned framework bump. No PHP extension or infrastructure dependency; the only external coupling is Font Awesome, and only for the default icon classes in the Blade directive.

Migration path. Adopt incrementally, per resource, not as a sweep. Sequence: (1) publish config/columnsortable.php and review it against our design system — replace the FA4/FA5 suffix and class defaults with our own icon classes, since shipping Font Awesome assumptions in backend config is a presentation leak; (2) add Sortable and an explicit $sortable array to one high-traffic read model, deliberately never relying on Schema::hasColumn(); (3) wire ->sortable() into that controller and @sortablelink into its Blade partial; (4) add ColumnSortableException handling at the controller boundary; (5) expand to remaining index pages. Keep $sortable arrays next to the model, not derived, so the whitelist is reviewable in a diff.

Compatibility. Verify in CI against our locked Laravel and PHP versions, and against MariaDB and PostgreSQL if we run both — relation sorting and withCount aliasing exercise orderBy on joined and aliased columns, which is exactly where engines diverge. Confirm interaction with paginate() links (the README's appends(\Request::except('page')) pattern is required, not optional — omitting it silently drops the sort across pages). If we already use a data-table library or a query-filter package (e.g. Spatie Query Builder), pick one per resource; running both on the same model creates two competing orderBy authorities.

Sequencing. Config and icon theming first, then one pilot model with relation-free sorting, then relation/alias patterns only if a concrete screen needs them. Defer the {column}Sortable override mechanism until a real join is required; it is the least-tested and most app-specific surface. Budget a short spike to confirm the package's stated framework support against our matrix before the pilot, so we do not discover drift mid-migration.

Operational Impact

Maintenance. Low ongoing cost, high bus-factor exposure. The package is small, MIT, and stable in behavior; but support for new Laravel majors has arrived via automated contributor PRs, so our framework upgrade cadence becomes dependent on a third party's bot running on time. Mitigation: treat the package as vendorable. Because the surface we actually use (whitelist + scope + directive) is small, we should be willing and able to fork or inline it during a framework upgrade rather than being blocked. Track the upstream repo's release activity as an explicit line item in our Laravel upgrade checklist.

Support. Community-only, GitHub issues, no vendor SLA. Documentation is good in the README and configuration file, with a linked example repository, but it is drifting relative to releases — the compatibility header is the clearest example. Plan for our own internal one-pager: our pinned version, our config customizations, our whitelist convention, and our exception-handling pattern. That document is the actual support contract.

Scaling. Sorting happens in the database, so application-tier scale is unaffected. Watch three things: (1) the Schema::hasColumn() fallback fires an extra schema query per request for any model lacking $sortable — enforce explicit whitelists and, better, add a lint or code-review check; (2) sortable columns must be indexed, since ORDER BY on an unindexed column with LIMIT/OFFSET pagination degrades badly on large tables; (3) relation sorting generates joins at query time, so validate query plans for the specific screens that use it. Deep-offset pagination is the real ceiling, and it is a pagination problem, not a package problem.

Failure modes. (a) Unhandled ColumnSortableException — the README explicitly warns that a crafted sort parameter (e.g. detail..phone_number) throws code 0; without a controller-level catch this is a user-triggerable 500 and a cheap denial-of-service. (b) Invalid relation — code 1/2 when the relation name is wrong or is not a hasOne, which surfaces as an error page rather than a graceful fallback. (c) Combining two different relations in one request, which the README flags as producing "relation is not defined" errors. (d) Implicit schema-derived whitelisting allowing a sort on a column we never intended to expose. (e) Sort state lost across pagination if appends() is omitted. (f) Silent behavior change on a framework upgrade if the constraint is left loose.

Ramp-up. Very shallow for anyone fluent in Eloquent — the mental model is "a scope plus a directive," learnable in an afternoon from the README. The real ramp-up cost is convention, not API: teams must consistently declare $sortable, catch the exception, and theme the icons. Codify those three in the starter template or a shared Blade component so new index pages inherit them rather than rediscovering them per screen.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
se7enxweb/flysystem
lampwick/laravel
jeslage/statamic-emojis
micahdshackelford/rmap-laravel
draftsmaninc/draftsman
square-bit/laravel-volition
himito/laravel-mailman
htinlynn/genius-helper
maco-studios/hephaestus
elmogy/larafast
xeviant/laravel-paystack
gorilladash/laravel-website-sdk
martialbe/flysystem-oss
chondal/3312client
jeroen-g/flickr
opscale-co/nova-genbi
itsjustvita/laravel-retention
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log