最近專案有多個不同型別前端,所以在給api返回資料的時候需要隱藏某些欄位
之前看了一篇文章在 Laravel 中動態隱藏 API 欄位覺得還是有點不方便,所以就自己弄了一個。
目前實現了三個方法
- 設定隱藏的欄位
hide
方法 - 設定顯示的欄位
show
方法 - 設定型別
type
方法(在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']);
最後說一個設定型別的作用,一個資原始檔要處理不同型別的資料,比如一個是給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類通過隱藏一些在其他介面允許暴露的欄位從而變得更加靈活,可能會有問題,目前我還沒遇到,今天才弄出來的~~~
如果有型別需求的小夥伴用了這個發現問題可以討論哦~~~
本作品採用《CC 協議》,轉載必須註明作者和本文連結