Laravel 7/8 非集合场景下Resource模板指定返回字段排除实现方法
可行实现方案
方案1:直接使用whenLoaded闭包适配现有代码
你现有的CompanyResource已经实现了单个实例的hide方法,只需要处理whenLoaded可能返回空值的问题即可,修改UserResource中company字段的定义:
public function toArray($request) { return [ 'id' => $this->id, 'email' => $this->email, 'status' => $this->status, 'timezone' => $this->timezone, 'last_name' => $this->last_name, 'first_name' => $this->first_name, 'tags' => TagResource::collection($this->whenLoaded('tags')), // 修改此处代码 'company' => $this->whenLoaded('company', function () { return (new CompanyResource($this->company))->hide(['company_logo']); }), ]; }
这种写法只有当company关联确实被加载时,才会实例化CompanyResource并调用hide方法隐藏指定字段,不会出现空对象调用方法的报错。
补充:修复集合隐藏的潜在问题
如果你之前的集合hide调用已经正常生效,说明你已经实现了CompanyResourceCollection类的对应方法;如果未生效,需要在CompanyResourceCollection中添加如下代码,保证集合下的所有单个资源都能继承隐藏字段配置:
// app/Http/Resources/CompanyResourceCollection.php namespace App\Http\Resources; use Illuminate\Http\Resources\Json\ResourceCollection; class CompanyResourceCollection extends ResourceCollection { protected $withoutFields = []; public function hide(array $fields) { $this->withoutFields = $fields; return $this; } public function toArray($request) { return $this->collection->map(function ($resource) use ($request) { return $resource->hide($this->withoutFields)->toArray($request); })->all(); } }
方案2:通用化封装(可选)
如果需要在多个资源类中复用字段隐藏能力,可以把相关逻辑抽成Trait,所有资源类引入即可:
// app/Http/Resources/Traits/HidesFields.php namespace App\Http\Resources\Traits; trait HidesFields { protected $withoutFields = []; public function hide(array $fields) { $this->withoutFields = $fields; return $this; } protected function filterFields(array $array) { return collect($array)->forget($this->withoutFields)->toArray(); } }
之后在CompanyResource中引入Trait即可复用逻辑:
class CompanyResource extends JsonResource { use \App\Http\Resources\Traits\HidesFields; // 其余原有代码保持不变 }
内容的提问来源于stack exchange,提问作者Lehlohonolo Motsoeneng
相关产品推荐
相关产品推荐

