文章轉發自專業的Laravel開發者社區,原始連接:learnku.com/laravel/t/7…php
我最近在 Laravel Brasil 社區看到一個問題,結果比看起來更有趣。想象一下你有一個 UsersResource
用下面的實現:laravel
<?php
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\Resource;
class UsersResource extends Resource
{
/**
* Transform the resource into an array.
*
* @param \Illuminate\Http\Request
* @return array
*/
public function toArray($request)
{
return [
'id' => $this->id,
'name' => $this->name,
'email' => $this->email
];
}
}
複製代碼
出於某種緣由,您可能但願在另外一個端點上從新使用該資源類,但隱藏email
字段。這篇文章就是告訴你如何實現這一點的。 若是你不知道 API Resources
是什麼,請查看我以前關於這個的文章。git
有趣的東西從第3節開始.github
composer create-project --prefer-dist laravel/laravel api-fields
cd api-fields
touch database/database.sqlite
複製代碼
編輯.env
文件,刪除數據庫設置並使用 SQLitesql
DB_CONNECTION=sqlite
複製代碼
繼續設置項目數據庫
php artisan migrate
php artisan make:resource UsersResource
php artisan make:resource --collection UsersResourceCollection
php artisan make:controller UsersController
php artisan tinker
factory(App\User::class)->times(20)->create();
quit
複製代碼
確保在 api.php
文件中建立一個路由。api
Route::apiResource('/users', 'UsersController');
複製代碼
控制器表明了指望的目標。在這個例子中,讓咱們假設在用戶列表中,咱們只想要全部用戶的名字,而在用戶顯示中,咱們只想隱藏電子郵件地址。數組
<?php
namespace App\Http\Controllers;
use App\Http\Resources\UsersResource;
use App\User;
class UsersController extends Controller
{
/**
* Display a listing of the resource.
*
* @param User $user
* @return \Illuminate\Http\Response
*/
public function index(User $user)
{
return UsersResource::collection($user->paginate())->hide(['id', 'email']);
}
/**
* Display a user.
*
* @param User $user
* @return \Illuminate\Http\Response
*/
public function show(User $user)
{
return UsersResource::make($user)->hide(['id']);
}
}
複製代碼
爲了達到這個目的,咱們須要 UsersResourceCollection
和UsersResource
同時知道如何處理 hide
調用。bash
讓咱們從 show
方法開始. UsersResource::make
將會返回 UsersResource
的對象. 所以,咱們應該揭開 hide
的神祕面紗,它能夠存儲咱們指望從響應中移除的鍵.php7
<?php
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\Resource;
class UsersResource extends Resource
{
/**
* @var array
*/
protected $withoutFields = [];
/**
* Transform the resource into an array.
*
* @param \Illuminate\Http\Request
* @return array
*/
public function toArray($request)
{
return $this->filterFields([
'id' => $this->id,
'name' => $this->name,
'email' => $this->email
]);
}
/**
* Set the keys that are supposed to be filtered out.
*
* @param array $fields
* @return $this
*/
public function hide(array $fields)
{
$this->withoutFields = $fields;
return $this;
}
/**
* Remove the filtered keys.
*
* @param $array
* @return array
*/
protected function filterFields($array)
{
return collect($array)->forget($this->withoutFields)->toArray();
}
}
複製代碼
大功告成! 如今咱們能夠訪問 http://api.dev/api/users/1
,你會發現響應中已經沒有id
字段了。
{
"data": {
"name": "Mr. Frederik Morar",
"email": "darryl.wilkinson@example.org"
}
}
複製代碼
執行項目集合中的 index
方法, 咱們須要做出以下修改:
UsersResource::collection
返回 UsersResourceCollection
實例UsersResourceCollection
上公開 hide
方法UsersResource
關於 (1), 咱們只須要重寫 UsersResource
中的 collection
方法
<?php
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\Resource;
class UsersResource extends Resource
{
public static function collection($resource)
{
return tap(new UsersResourceCollection($resource), function ($collection) {
$collection->collects = __CLASS__;
});
}
/**
* @var array
*/
protected $withoutFields = [];
/**
* Transform the resource into an array.
* 將資源轉換爲一個數組
*
* @param \Illuminate\Http\Request
* @return array
*/
public function toArray($request)
{
return $this->filterFields([
'id' => $this->id,
'name' => $this->name,
'email' => $this->email
]);
}
/**
* Set the keys that are supposed to be filtered out.
* 設置須要隱藏過濾掉的鍵
*
* @param array $fields
* @return $this
*/
public function hide(array $fields)
{
$this->withoutFields = $fields;
return $this;
}
/**
* Remove the filtered keys.
* 刪除隱藏的鍵
*
* @param $array
* @return array
*/
protected function filterFields($array)
{
return collect($array)->forget($this->withoutFields)->toArray();
}
}
複製代碼
關於 (2) 和 (3) 咱們須要修改 UsersResourceCollection
文件. 讓咱們公開 hide
方法並使用隱藏字段處理集合。.
<?php
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\ResourceCollection;
class UsersResourceCollection extends ResourceCollection
{
/**
* @var array
*/
protected $withoutFields = [];
/**
* Transform the resource collection into an array.
*
* @param \Illuminate\Http\Request
* @return array
*/
public function toArray($request)
{
return $this->processCollection($request);
}
public function hide(array $fields)
{
$this->withoutFields = $fields;
return $this;
}
/**
* Send fields to hide to UsersResource while processing the collection.
* 將隱藏字段經過 UsersResource 處理集合
*
* @param $request
* @return array
*/
protected function processCollection($request)
{
return $this->collection->map(function (UsersResource $resource) use ($request) {
return $resource->hide($this->withoutFields)->toArray($request);
})->all();
}
}
複製代碼
就是這麼簡單! 如今咱們訪問 http://api.dev/api/users
看到返回結果中沒有了 id
和 email
字段瞭如在 UsersController
中的指定方法 .
{
"data": [{
"name": "Mr. Frederik Morar"
}, {
"name": "Angel Daniel"
}, {
"name": "Brianne Mueller"
}],
"links": {
"first": "http://lab.php71/api-fields-2/public/api/users?page=1",
"last": "http://lab.php71/api-fields-2/public/api/users?page=7",
"prev": null,
"next": "http://lab.php71/api-fields-2/public/api/users?page=2"
},
"meta": {
"current_page": 1,
"from": 1,
"last_page": 7,
"path": "http://api-fields.lab.php71/api/users",
"per_page": 3,
"to": 3,
"total": 20
}
}
複製代碼
本文目標是讓Resource
類經過隱藏一些在其餘接口容許暴露的字段從而變得更加靈活。例如當咱們請求/users
接口時響應的數據是不包含avatar
字段的,可是當請求/users/99
時響應的數據裏包含avatar
字段。
我不推薦過分重複去請求API資源,由於它極可能會把簡單的事情變得更加複雜,因此說在請求的時候隱藏某些特定的字段是更簡單、更合理的解決方案。