在 Laravel 中动态隐藏 API 字段的方法


Posted in PHP onOctober 25, 2019

我最近在 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
  ];
 }
}

出于某种原因,您可能希望在另一个端点上重新使用该资源类,但隐藏email 字段。这篇文章就是告诉你如何实现这一点的。

如果你不知道 API Resources 是什么,请查看我之前关于这个的文章。

  • First Impression on API Resources
  • API Resources with Nested Relationship

1- 初始化项目

有趣的东西从第3节开始.

composer create-project --prefer-dist laravel/laravel api-fields
cd api-fields
touch database/database.sqlite

编辑.env文件,删除数据库设置并使用 SQLite

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

2- 路由

确保在 api.php 文件中创建一个路由。

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 的对象. 因此,我们应该揭开  hide 的神秘面纱,它可以存储我们期望从响应中移除的键.

<?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"
 }
}

5- UsersResourceCollection 类

执行项目集合中的 index 方法, 我们需要作出如下修改:

(1) 确保  UsersResource::collection 返回 UsersResourceCollection 实例

(2) 在  UsersResourceCollection 上公开 hide 方法

(3) 将隐藏的字段传递给  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
 }
}

6- 总结

本文目标是让Resource类通过隐藏一些在其他接口允许暴露的字段从而变得更加灵活。例如当我们请求/users接口时响应的数据是不包含avatar字段的,但是当请求/users/99时响应的数据里包含avatar字段。

我不推荐过度重复去请求API资源,因为它很可能会把简单的事情变得更加复杂,所以说在请求的时候隐藏某些特定的字段是更简单、更合理的解决方案。

以上所述是小编给大家介绍的在 Laravel 中动态隐藏 API 字段的方法,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!

PHP 相关文章推荐
Get或Post提交值的非法数据处理
Oct 09 PHP
不错的PHP学习之php4与php5之间会穿梭一点点感悟
May 03 PHP
php Undefined index的问题
Jun 01 PHP
php判断变量类型常用方法
Apr 24 PHP
使用 PHPMAILER 发送邮件实例应用
Nov 07 PHP
使用phpQuery采集网页的方法
Nov 13 PHP
PHP使用mysqldump命令导出数据库
Apr 14 PHP
Windows Server 2008 R2和2012中PHP连接MySQL过慢的解决方法
Jul 02 PHP
详谈PHP面向对象中常用的关键字和魔术方法
Feb 04 PHP
php获取ip及网址的简单方法(必看)
Apr 01 PHP
thinkPHP5框架设置404、403等http状态页面的方法
Jun 05 PHP
PHP实现负载均衡session共享redis缓存操作示例
Aug 22 PHP
Laravel 实现添加多语言提示信息
Oct 25 #PHP
Laravel5.5 动态切换多语言的操作方式
Oct 25 #PHP
解决php扩展安装不生效问题
Oct 25 #PHP
Laravel实现通过blade模板引擎渲染视图
Oct 25 #PHP
laravel 解决Validator使用中出现的问题
Oct 25 #PHP
laravel接管Dingo-api和默认的错误处理方式
Oct 25 #PHP
Laravel 解决419错误 -ajax请求错误的问题(CSRF验证)
Oct 25 #PHP
You might like
一个可查询所有表的“通用”查询分页类
2006/10/09 PHP
PHP编码规范之注释和文件结构说明
2010/07/09 PHP
php上传图片到指定位置路径保存到数据库的具体实现
2013/12/30 PHP
PHP中模拟链表和链表的基本操作示例
2016/02/27 PHP
PHP的Yii框架中使用数据库的配置和SQL操作实例教程
2016/03/17 PHP
php自动提交表单的方法(基于fsockopen与curl)
2016/05/09 PHP
解决PHP上传非标准格式的图片pjpeg失败的方法
2017/03/12 PHP
解析ScrollPic在ie8下只滚动一遍,然后变为空白 ie6,ie7,chrome,firefox正常
2013/06/26 Javascript
javascript模拟post提交隐藏地址栏的参数
2014/09/03 Javascript
使用js Math.random()函数生成n到m间的随机数字
2014/10/09 Javascript
浅谈类似于(function(){}).call()的js语句
2015/03/30 Javascript
JavaScript严格模式详解
2015/11/18 Javascript
jQuery实现的简单排序功能示例【冒泡排序】
2017/01/13 Javascript
input type=file 选择图片并且实现预览效果的实例
2017/10/26 Javascript
JavaScript折半查找(二分查找)算法原理与实现方法示例
2018/08/06 Javascript
node中实现删除目录的几种方法
2019/06/24 Javascript
ES6的循环与可迭代对象示例详解
2021/01/31 Javascript
Python中的map、reduce和filter浅析
2014/04/26 Python
10个易被忽视但应掌握的Python基本用法
2015/04/01 Python
使用Python的Twisted框架实现一个简单的服务器
2015/04/16 Python
Python中使用bidict模块双向字典结构的奇技淫巧
2016/07/12 Python
Python查看微信撤回消息代码
2018/06/07 Python
对Python实现简单的API接口实例讲解
2018/12/10 Python
Python redis操作实例分析【连接、管道、发布和订阅等】
2019/05/16 Python
使用批处理脚本自动生成并上传NuGet包(操作方法)
2019/11/19 Python
django queryset相加和筛选教程
2020/05/18 Python
Myprotein蛋白粉美国官网:欧洲畅销运动营养品牌
2016/11/15 全球购物
美国隐形眼镜网上商店:Lens.com
2019/09/03 全球购物
电大物流学生的自我评价
2013/10/25 职场文书
建筑设计学生的自我评价
2014/01/16 职场文书
庆元旦广播稿
2014/02/10 职场文书
2014年学校卫生工作总结
2014/11/20 职场文书
2014年教学管理工作总结
2014/12/02 职场文书
聘任通知书
2015/09/21 职场文书
redis sentinel监控高可用集群实现的配置步骤
2022/04/01 Redis
Java实现注册登录跳转
2022/06/16 Java/Android