如何在Laravel API资源中添加自动递增的用户排名字段
给Laravel API资源添加自动递增的排名字段
嘿,这个需求其实很好实现,咱们分两种方案来做,看你更倾向哪一种:
方案一:快速修改控制器+资源
这种方式不需要新建额外文件,直接在现有代码上调整就行:
首先,在控制器里过滤完数据后,用map方法给每个用户模型动态添加ranking属性,集合的索引刚好就是咱们要的递增排名(从0开始):
$data = User::with('city') ->withCount('point') ->orderByDesc('points_count') ->get(); $data = $data->where('points_count', '!=', 0); // 给每个用户添加排名字段,索引从0开始 $data = $data->map(function ($user, $index) { $user->ranking = $index; return $user; }); return UserPointResource::collection($data);
然后在你的UserPointResource里,新增ranking字段即可,顺便给city字段补个默认值避免空关联报错:
return [ "id" => (int)$this->id, "fullname" => $this->fullname, "city" => $this->city ? $this->city->name : null, "count" => (int)$this->points_count, "ranking" => (int)$this->ranking, // 新增的排名字段 ];
方案二:用自定义资源集合(更优雅)
如果想让代码逻辑更内聚,符合Laravel资源的设计理念,可以创建一个自定义的资源集合类:
- 在
app/Http/Resources目录下新建UserPointCollection.php:
namespace App\Http\Resources; use Illuminate\Http\Resources\Json\ResourceCollection; class UserPointCollection extends ResourceCollection { public function toArray($request) { // 遍历集合时直接给每个用户加上排名 return $this->collection->map(function ($user, $index) { return [ "id" => (int)$user->id, "fullname" => $user->fullname, "city" => $user->city ? $user->city->name : null, "count" => (int)$user->points_count, "ranking" => $index, // 要从1开始排名的话,改成 $index + 1 就行 ]; }); } }
- 然后在控制器里返回这个集合:
$data = User::with('city') ->withCount('point') ->orderByDesc('points_count') ->get(); $data = $data->where('points_count', '!=', 0); return new UserPointCollection($data);
这样就不用修改原来的UserPointResource了,所有和集合输出相关的逻辑都放在了资源集合里,后期维护起来更方便。
补充说明
因为你已经通过orderByDesc('points_count')把用户按积分降序排好,又过滤掉了0积分的用户,所以集合的顺序完全符合排名逻辑,直接用循环的索引作为排名值就没问题。要是之后需要调整排名起始值(比如从1开始),只需要修改索引的计算方式即可。
内容的提问来源于stack exchange,提问作者Farshad
相关产品推荐
相关产品推荐

