要详细说明我的评论,这里有一个答案。
您不能使用虚拟属性(例如您想要的getFullNameAttribute())进行排序和过滤。即使它有效,它也会在内存中执行,因为这些访问器无法被 Laravel 自动转换为 SQL。
相反,您可以在 SQL 中重新创建所需的访问器。仅此还不够,因为 yajra 的 DataTables 包不能按表达式排序,只能按列名排序。因此,您必须将整个查询包装在另一个查询中。示例:
class UserDataTable extends DataTable
{
public function query(): \Illuminate\Database\Query\Builder
{
return DB::query()->fromSub(
User::query()
->select([
'*',
DB::raw("CONCAT(first_name, ' ', last_name) as full_name")
]),
'wrapped'
);
}
protected function getColumns(): array
{
return [
['data' => 'first_name', 'title' => 'First Name'],
['data' => 'last_name', 'title' => 'Last Name'],
['data' => 'full_name', 'title' => 'Full Name'],
];
}
}
请注意,用DB::query()->fromSub(...) 包裹表格会阻止您在过滤器部分中使用类型提示:
public function dataTable($query): DataTableAbstract
{
/** @var QueryDataTable $dataTable */
$dataTable = datatables($query);
return $dataTable
->editColumn('first_name', function ($user) {
/** @var User|\stdClass $user */
return ucfirst($user->first_name);
});
}
使用/** @var User|\stdClass $user */ 是一种在函数参数中没有类型提示的情况下仍然获得 IDE 支持的方法。