Laravel Yajra DataTables关联排序报错及ID返回异常问题求解
问题原因分析
- 问题1原因:
kabupaten和provinsi两个表的id字段同名,预加载provinsi时如果没有指定查询字段,provinsi表的id会覆盖主表kabupaten的id,导致视图中拿到的$id是关联表的ID。 - 问题2原因:
with()实现的是预加载(执行两次独立查询),没有做联表操作,排序时Yajra Datatable会直接在主表查询中添加order by provinsi.provinsi,而主表不存在该字段所以报错。
解决方案
方案一:使用联表查询(推荐,同时解决排序和搜索问题)
- 修改
query方法,改为leftJoin联表查询,给关联字段起别名避免冲突:
public function query(Kabupaten $model) { return $model->newQuery() ->leftJoin('provinsi', 'kabupaten.provinsi_id', '=', 'provinsi.id') ->select( 'kabupaten.*', 'provinsi.provinsi as nama_provinsi' ) ->with('provinsi'); // 保留预加载方便调用其他关联属性 }
- 修改
getColumns方法中provinsi列的定义,使用别名:
// 替换原来的 Column::make('provinsi.provinsi') Column::make('nama_provinsi')->title('Provinsi'),
方案二:保留预加载,自定义关联字段排序逻辑
如果不想改动查询结构,可在dataTable方法中添加自定义排序回调:
public function dataTable($query) { return datatables() ->eloquent($query) ->addIndexColumn() ->addColumn('kordinat', function(Kabupaten $kabupaten) { return $kabupaten->koordinat_bujur.",".$kabupaten->koordinat_lintang; }) ->addColumn('action', 'kabupaten.action') // 新增provinsi列的自定义排序逻辑 ->orderColumn('provinsi.provinsi', function ($query, $order) { $query->leftJoin('provinsi', 'kabupaten.provinsi_id', '=', 'provinsi.id') ->orderBy('provinsi.provinsi', $order); }); }
额外优化建议
为了彻底避免ID覆盖问题,建议在渲染action列时明确传递kabupaten的ID,不要依赖自动注入的$id变量:
// 替换原来的->addColumn('action', 'kabupaten.action') ->addColumn('action', function($data) { return view('kabupaten.action', [ 'id' => $data->id // 明确传递当前行kabupaten的ID ]); })
内容的提问来源于stack exchange,提问作者cangak
相关产品推荐
相关产品推荐

