如何基于Policy过滤API Resource?过滤集合无返回结果求指导
问题解决:API Resource中Policy过滤集合无返回结果
你遇到的核心问题是**filter闭包没有返回权限校验的结果**。Laravel集合的filter方法要求闭包返回布尔值,来决定是否保留当前元素,你的代码仅执行了Auth::user()->can('view', $item),但没有将这个结果返回,导致所有元素都被判定为不符合条件,最终返回空集合。
修正代码
将accessible_projects的过滤逻辑修改为:
<?php namespace App\Http\Resources; use Illuminate\Http\Request; use Illuminate\Http\Resources\Json\JsonResource; use Illuminate\Support\Facades\Auth; class UserResource extends JsonResource { /** * Transform the resource into an array. * * @return array<string, mixed> */ public function toArray(Request $request): array { return [ 'name' => $this->name, 'email' => $this->email, 'client_id' => $this->client->id, 'role' => $this->role->name, 'accessible_projects' => $this->client->projects->filter(function ($item) { // 关键:返回权限校验的结果 return Auth::user()->can('view', $item); }), // 或者用箭头函数简化写法 // 'accessible_projects' => $this->client->projects->filter(fn($item) => Auth::user()->can('view', $item)), ]; } }
额外优化建议
避免N+1查询:在控制器查询用户数据时,提前预加载
client.projects和role关联,提升性能:// 控制器示例 $user = User::with('client.projects', 'role')->findOrFail($id); return new UserResource($user);数据库层面过滤更高效:如果这个权限过滤是全局需求,建议在模型中定义一个关联,直接在数据库层面过滤数据,比集合过滤性能更好(尤其数据量大时):
// Client模型中添加关联 public function accessibleProjects() { return $this->projects()->where(function ($query) { // 这里复用Policy中`view`权限的逻辑 $user = Auth::user(); if ($user->can('view-all-projects')) { return; } // 示例:仅返回用户参与的项目 $query->whereHas('members', fn($q) => $q->where('user_id', $user->id)); }); }之后在Resource中直接调用这个关联:
'accessible_projects' => $this->client->accessibleProjects,
内容的提问来源于stack exchange,提问作者DiTrain
相关产品推荐
相关产品推荐

