商城首页欢迎来到中国正版软件门户

您的位置: 首页 > 文章列表 > 编程开发 > ThinkPHP中Model的hidden属性_输出时隐藏敏感字段【操作】

ThinkPHP中Model的hidden属性_输出时隐藏敏感字段【操作】

  发布于2026-05-23 阅读(0)

扫一扫,手机访问

ThinkPHP中Model的hidden属性:输出时隐藏敏感字段的真相与陷阱

ThinkPHP中Model的hidden属性_输出时隐藏敏感字段【操作】

在ThinkPHP开发中,模型层的$hidden属性常被用来过滤敏感字段,比如密码。但你真的了解它的生效边界吗?一个常见的误解是,只要在模型里设置了$hidden,数据库就查不出这个字段,或者它无论如何都不会泄露。事实并非如此。这个机制有明确的生效范围,用错了场景,敏感数据依然会“大摇大摆”地暴露出来。

hidden 只作用于 toArray() 和 toJson() 等序列化过程

首先要明确一点:$hidden是一个“输出过滤器”,而非“查询过滤器”。它不会阻止数据库查询语句去获取password字段。它的工作,仅仅是在模型实例被序列化为数组或JSON时,将指定的键从最终结果里剔除。理解这一点,就能看懂下面几种情况的差异:

  • User::find(1)->toArray() ✅ 这是$hidden属性的主场,它会生效。
  • User::find(1)->toJson() ✅ 底层通常调用toArray(),因此同样受$hidden控制。
  • json_encode(User::find(1)) ❌ 这行代码直接对模型对象进行序列化,绕过了模型的toArray逻辑,$hidden规则完全失效。
  • User::field('id,password')->find(1)->toArray() ❌ 数据库查询时已经明确查出了password字段,$hidden只是在后续toArray()时选择不显示它,但数据已经被加载到模型属性中了。这可不是真正的“安全”。

字段名必须严格匹配,且仅限当前模型原始字段

配置$hidden时,细节决定成败。字段名必须与数据库表的列名严格一致,大小写、下划线都不能错。更重要的是,它的作用范围仅限于当前模型自身的原始字段。

  • 如果数据库列是user_id,那么在$hidden数组里就必须写'user_id',写成'userId''User_id'都不会生效。
  • 你在User模型里设置了protected $hidden = ['password'],但这管不到它的关联模型。假设User关联了一个Profile模型,Profile里的id_card(身份证号)字段依然会被原样输出。
  • 想要隐藏关联模型的字段,必须在Profile模型内部也单独配置protected $hidden = ['id_card']
  • 通过append属性添加的虚拟访问器字段(例如_mobile_masked),默认也不受$hidden管理。如果需要隐藏它们,必须显式地将这些虚拟字段名也加入到$hidden数组中。

别踩这些常见的“坑”

很多开发者遇到“$hidden不生效”的问题,根源在于代码逻辑根本没走到它生效的那一步。下面这些场景,都是典型的“坑”:

立即学习“PHP免费学习笔记(深入)”;

  • 使用了toArray(true) —— 这里的true参数表示强制进行全量导出,它会使得$hidden$visible(可见字段)的配置全部失效。
  • 手动拼接数组返回:像['id' => $user->id, 'password' => $user->password]这样直接读取对象属性来构造数组,完全绕过了模型的所有输出处理逻辑,$hidden自然不起作用。
  • 直接使用Db门面查询:Db::name('user')->select()返回的是纯粹的数据数组,而不是模型对象实例。既然不经过模型,模型的$hidden属性也就无从谈起了。
  • 试图在控制器运行时动态修改:$user->hidden = ['password']。请注意,$hidden是模型的类属性(protected),而非对象属性。这种运行时赋值通常是无效的。

安全建议:优先考虑使用 visible 白名单

从安全角度出发,相比于用$hidden来“隐藏不想显示的”(黑名单模式),更推荐使用$visible来“指定允许显示的”(白名单模式)。白名单策略更加主动和可控,尤其适用于字段众多、权限要求精细的接口场景。

  • 可以删掉$hidden配置,转而定义protected $visible = ['id', 'username', 'a vatar']
  • 白名单支持动态切换,灵活性更高:$user->visible(['id','username'])->toArray()
  • 同样需要记住,关联模型的$visible配置是独立的,不会继承自主模型的设置。
  • 一个小提示:将$visible设置为空数组[],意味着“一个字段都不返回”,而不是“返回全部字段”。
本文转载于:https://www.php.cn/faq/2421965.html 如有侵犯,请联系zhengruancom@outlook.com删除。
免责声明:正软商城发布此文仅为传递信息,不代表正软商城认同其观点或证实其描述。

热门关注