Laravel如何仅在特定路由展示API资源的特定字段
回答
完全可以实现,以下是两种生产环境常用的可行方案,不会影响原有10个路由的返回逻辑:
方案1:资源类传参标识(推荐,耦合度更低)
核心逻辑是给UserResource增加可选的构造参数,标记是否需要返回posts字段,原有路由调用时不传参走默认逻辑,仅第11个路由调用时传入显式标识。
先修改UserResource代码:class UserResource extends JsonResource { protected bool $showPosts = false; public function __construct($resource, bool $showPosts = false) { parent::__construct($resource); $this->showPosts = $showPosts; } public function toArray($request) { $baseFields = [ 'id' => $this->id, 'name' => $this->name, 'email' => $this->email, ]; if ($this->showPosts) { // whenLoaded避免关联未预加载时抛出异常,同时防止N+1问题 $baseFields['posts'] = PostResource::collection($this->whenLoaded('posts')); } return $baseFields; } }原有10个路由的调用代码完全不需要改动,默认
$showPosts为false,不会返回posts字段;仅在第11个路由的控制器逻辑中,传参开启字段展示即可:// 第11个路由对应的控制器方法,记得提前预加载posts关联 $user = User::with('posts')->findOrFail($id); return new UserResource($user, true);方案2:资源类内判断当前路由(零改动原有调用代码)
如果不想修改任何原有资源调用的代码,可以直接在toArray方法中判断当前请求匹配的路由,仅命中第11个路由时追加字段:public function toArray($request) { $baseFields = [ 'id' => $this->id, 'name' => $this->name, 'email' => $this->email, ]; // 替换为第11个路由的实际命名,也可以用$request->is('对应路径')判断 if ($request->routeIs('user.detail.with-posts')) { $baseFields['posts'] = PostResource::collection($this->whenLoaded('posts')); } return $baseFields; }该方案的缺点是资源类和路由规则强耦合,后续如果修改第11个路由的名称或路径,需要同步修改这里的判断条件。
注意:无论使用哪种方案,返回关联字段时都建议配合
whenLoaded方法,同时在对应控制器中提前预加载关联数据,避免产生N+1查询拖慢接口性能。
内容的提问来源于stack exchange,提问作者Abduhafiz
相关产品推荐
相关产品推荐

