Laravel中尝试用资源集合返回DataTable JSON数据的技术问询
嘿,看起来你想把现有的DataTables实现切换成用Laravel Eloquent资源集合来返回所需的JSON数据对吧?之前用QueryBuilder搭配DataTables包的代码已经跑通了,那咱们来一步步改成用资源集合的方式:
1. 创建Eloquent资源及资源集合
首先得创建对应Client模型的资源类,用来定义返回的字段结构,包括关联的accounts:
先执行Artisan命令生成资源:
php artisan make:resource ClientResource
然后编辑生成的ClientResource.php,定义要返回的字段,同时处理关联数据:
// app/Http/Resources/ClientResource.php namespace App\Http\Resources; use Illuminate\Http\Resources\Json\JsonResource; class ClientResource extends JsonResource { public function toArray($request) { return [ 'id' => $this->id, 'number' => $this->number, // 这里添加其他你需要返回的客户端字段 'accounts' => AccountResource::collection($this->whenLoaded('accounts')), ]; } }
接下来创建资源集合类,用来包装数据成DataTables需要的格式(外层带data字段,可选分页统计信息):
php artisan make:resource ClientCollection
编辑ClientCollection.php:
// app/Http/Resources/ClientCollection.php namespace App\Http\Resources; use Illuminate\Http\Resources\Json\ResourceCollection; class ClientCollection extends ResourceCollection { public function toArray($request) { // 严格匹配DataTables的JSON响应格式 return [ 'data' => $this->collection, // 如果需要前端显示总记录数、过滤后记录数,加上这两个字段 'recordsTotal' => $this->total(), 'recordsFiltered' => $this->total(), ]; } }
2. 修改控制器的index方法
原来的代码依赖DataTables包自动处理请求参数,现在要手动处理DataTables前端传来的分页、搜索、排序参数,同时用我们的资源集合返回数据:
public function index() { // 初始化QueryBuilder,保留你原来的allowedIncludes配置 $query = QueryBuilder::for(Client::class) ->allowedIncludes('accounts'); // 处理DataTables的全局搜索 if ($searchValue = request()->input('search.value')) { $query->where(function($q) use ($searchValue) { $q->where('id', 'like', "%{$searchValue}%") ->orWhere('number', 'like', "%{$searchValue}%"); // 这里可以添加其他需要支持搜索的字段 }); } // 处理排序请求 if ($order = request()->input('order.0')) { $columnIndex = $order['column']; $sortDirection = $order['dir']; // 映射前端列索引到数据库字段,要和你DataTables前端的列配置对应 $columnMap = [ 0 => 'id', 1 => 'number', // 添加其他列的映射关系 ]; if (isset($columnMap[$columnIndex])) { $query->orderBy($columnMap[$columnIndex], $sortDirection); } } // 处理分页,默认每页10条,对应DataTables的length参数 $perPage = request()->input('length', 10); $clients = $query->paginate($perPage); if (request()->ajax()) { // 用我们的资源集合返回符合格式的JSON return new ClientCollection($clients); } return view('client.index', compact('clients')); }
3. 几个关键注意点
- 确保你的前端DataTables配置开启了
serverSide: true,因为现在我们自己处理所有服务器端逻辑 whenLoaded('accounts')可以避免N+1查询问题,和你原来的allowedIncludes配合使用,只有当请求中包含include=accounts时才加载关联数据- 如果你的DataTables有自定义列,要同步更新
columnMap的映射关系,不然排序会失效
内容的提问来源于stack exchange,提问作者Bill Garrison
相关产品推荐
相关产品推荐

