最近项目有多个不同类型前端, 所以在给 api 返回数据的时候需要隐藏某些字段 之前看了一篇文章在 Laravel 中动态隐藏 API 字段觉得还是有点不方便, 所以就自己弄了一个 目前实现了三个方法
设置隐藏的自动
设置显示的字段
设置类型 (在 toArray 里面判断类型返回相应的数据)
Resource 实现
首先看 Resource 如何实现 自定义一个 BaseResource 继承 Resource 额! 直接上代码吧
- class BaseResource extends Resource
- {
- protected $withoutFields = [];
- private $hide = true;
- protected $type = 'default';
- public function type(string $request)
- {
- $this->type = $request;
- return $this;
- }
- public function hide(array $fields)
- {
- $this->withoutFields = $fields;
- return $this;
- }
- public function show(array $fields)
- {
- $this->withoutFields = $fields;
- $this->hide = false;
- return $this;
- }
- protected function filterFields($array)
- {
- if (!$this->hide) {
- return collect($array)->only($this->withoutFields)->toArray();
- }
- return collect($array)->except($this->withoutFields)->toArray();
- }
- }
在相应的 Resource 从原来的 Resource 继承 BaseResource 继续上代码
- class Channel extends BaseResource
- {
- public function toArray($request)
- {
- return $this->filterFields([
- 'id' => $this->id,
- 'name' => $this->name,
- 'cover' => $this->cover,
- 'user'=>[
- 'nickname'=>'small-dog',
- 'avatar'=>'xxx'
- ]
- ]);
- }
- }
如何使用?? 很简单啦
- $channel = Channel::find(1);
- ChannelResource::make($channel)->hide(['name','user.nickname']);// 支持 . 来隐藏多维数组
ResourceCollection 实现
这个也差不多, 就一点细微的差别 定义一个
BaseResourceCollection
继承 ResourceCollection 额! 直接上代码吧
- class BaseResourceCollection extends ResourceCollection
- {
- protected $withoutFields = [];
- private $hide = true;
- protected $type = 'default';
- public function type(string $request)
- {
- $this->type = $request;
- return $this;
- }
- public function hide(array $fields)
- {
- $this->withoutFields = $fields;
- return $this;
- }
- public function show(array $fields)
- {
- $this->withoutFields = $fields;
- $this->hide = false;
- return $this;
- }
- public function toArray($request)
- {
- return [
- 'data' => $this->collection->map(function ($item) {
- if (!$this->hide) {
- return collect($item)->only($this->withoutFields)->all();
- }
- return collect($item)->except($this->withoutFields)->all();
- }),
- 'meta' => $this->when(!empty($this->pageMeta()), $this->pageMeta())
- ];
- }
- // 定义这个方法主要用于分页, 当用 josn 返回的时候是没有 links 和 meta 的
- public function pageMeta()
- {
- try {
- return [
- 'current_page' => $this->resource->currentPage(),
- 'last_page' => $this->resource->lastPage(),
- 'per_page' => $this->resource->perPage(),
- 'total' => $this->resource->total(),
- ];
- } catch (\BadMethodCallException $exception) {
- return [];
- }
- }
- }
自己的 Collection 继承
- BaseResourceCollection
- class ChannelCollection extends BaseResourceCollection
- {
- }
toArray 都可以省了, 哈哈哈!!! 使用方法
- $channel = Channel::query()->where('user_id', $user->id)->orderByDesc('id');
- $page = $channel->paginate(10);// 当用 get 的时候是没有 meta 这个字段的
- $data['list'] = ChannelCollection::make($page)->hide(['name','user.nickname']);
type 的用法
最后说一个设置类型的作用, 一个资源文件要处理不同类型的数据, 比如一个是给 APP 的, 一个是给商家后台的
- public function toArray($request)
- {
- if ($this->type == 'edit') {
- return $this->filterFields([
- 'id' => hashid_encode($this->id),
- ]);
- }
- return $this->filterFields([
- 'id' =>$this->id,
- ]);
- }
然后在使用的时候
- $channel = Channel::find(1);
- ChannelResource::make($channel)->type('edit')->hide(['name','user.nickname']);// 支持 . 来隐藏多维数组
总结
本文目标是让 Resource 类通过隐藏一些在其他接口允许暴露的字段从而变得更加灵活, 可能会有问题, 目前我还没遇到, 今天才弄出来的~~~
如果有类型需求的小伙伴用了这个发现问题可以讨论哦~~~
来源: https://juejin.im/post/5a9912ea5188255569186891