Code前端首页关于Code前端联系我们

如何在 Laravel 中动态隐藏 API 字段

terry 2年前 (2023-09-25) 阅读数 58 #后端开发

Laravel Brasil 的社区看到了一个问题,结果比表面上看起来更有趣。想象一下 UsersResource 是通过以下方式实现的:

<?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
  ];
 }
}

出于某种原因,您可能希望在另一个端点上重用资源类,但隐藏电子邮件字段。本文将告诉您如何实现这一目标。

如果您不知道什么是API资源,请查看我之前的文章。

1 - 项目初始化

有趣的事情从第 3 部分开始 2- 路径

确保在文件中创建路径。

Route::apiResource('/users', 'UsersController');

3- 控制器

控制器代表期望的目标。在此示例中,假设我们只想显示用户列表中所有用户的姓名,并且只想隐藏用户屏幕中的电子邮件地址。

<?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 调用。

4- UsersResource 类

让我们从 show 方法开始。 UsersResource::make 返回 UsersResource 对象。因此,我们需要揭开能够存储我们想要从答案中删除的密钥的奥秘。

<?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();
 }
}

完成!现在我们开始了解它,您会注意到响应中没有 ID 字段。?

(3)将隐藏字段传递给UsersResource

对于(1),我们只需要重写UsersResource的集合方法

<?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();
 }
}

就这么简单!现在我们访问一下,发现返回的结果中没有id和email字段,比如UsersController.fields中指定的方法,这样就变得更加灵活了。例如,当我们请求/users接口时,响应数据不包含头像字段,但当我们请求/users/99时,响应数据包含头像字段。

我不建议过多检索 API 资源,因为这可能会使简单的事情变得复杂,因此在请求时隐藏某些字段是一个更简单、更明智的解决方案。

版权声明

本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

热门