laravel-admin 的 sortable() 不生效,主因是默认排序(如 latest())优先级过高覆盖用户排序,且字段需真实存在、未被访问器修改、未漏选,关联字段还需预加载配合。

laravel-admin 的 sortable() 不生效,大概率不是字段没加,而是默认查询覆盖了排序逻辑。
为什么加了 sortable() 却点不动?
常见现象是:点击表头出现升序/降序图标,但数据顺序完全不变。这不是前端失效,而是后端查询时被提前的 orderBy 拦截了 —— 尤其当你在 $grid->model()->latest() 或 orderBy('created_at', 'desc') 这类调用后加 sortable(),框架会把「默认排序」和「用户触发排序」混在一起处理,而 latest() 是个特殊语法糖,它内部生成的 orderBy 优先级高、不可被后续 sortable 覆盖。
-
$grid->model()->latest()等价于orderBy('created_at', 'desc'),但 laravel-admin 1.5.7–1.8.x 版本对它的解析不完整,导致用户点击其他列排序时,原latest()仍强制生效 - 换成
$grid->model()->orderBy('created_at', 'desc')就正常,说明问题出在方法封装层,而非 SQL 层 - 如果模型本身定义了
$casts或访问器(accessor)影响了字段值(比如created_at被转成字符串),sortable()也会静默失效
检查排序字段是否被正确识别
laravel-admin 要求可排序字段必须满足两个条件:一是数据库真实存在且类型支持比较(不能是 JSON 字段或虚拟列),二是不能被 selectRaw、DB::raw 或模型访问器重写。
- 确认字段名和数据库列名完全一致,比如
created_at不能写成created_at_formatted - 避免在
$grid->model()->select(...)中漏掉排序字段,否则orderBy会报错或忽略 - 如果用了软删除(
SoftDeletes),确保没在model()中误加withTrashed()导致查询上下文异常 - 运行一次实际请求,在 Laravel 日志里搜
order by,看最终生成的 SQL 是否包含你点击列的ORDER BY
绕过默认排序干扰的实操方案
不要依赖 $grid->model()->latest() 做初始排序,改用更可控的方式:
- 删掉
$grid->model()->latest(),改用$grid->model()->orderBy('id', 'desc')(主键最稳妥) - 或者直接在控制器中设置默认排序:
$grid->model()->setOrderBy(['created_at' => 'desc']);(部分版本支持) - 若必须用
latest(),就别给其他字段加sortable();或者手动重写排序逻辑,在grid()里监听Grid::filtering事件做干预 - 升级到
dcat-admin(laravel-admin 的活跃分支),它已修复该问题,latest()和sortable()可共存
最容易被忽略的一点:sortable() 对关联字段(如 $grid->user->name()->sortable())默认不生效,必须配合 with() 预加载 + orderBy 显式拼接,否则点击时连 SQL 都不会加 JOIN。











