跳转到主内容
极星编程网:以代码为星,赴技术山海!

ThinkPHP怎么实现模型字段批量字段动态隐藏_ThinkPHP根据配置开关敏感字段【技巧】

ThinkPHP模型中hidden属性无法动态生效,因其为类属性且PHP解析时已固化;应改用visible白名单、访问器控制或查询层field过滤。 ThinkPHP 模型中用
hidden
属性动态控制字段不生效? 直接原因:模型的
hidden
是类属性,PHP 解析时就固化了,运行时改它没用。你以为
$model->hidden = ['id', 'password']
能起作用,其实序列化、
toArray()
、API 返回时还是按原始定义走。 真正生效的只有在模型类定义里写的
protected $hidden = ['password'];
想“动态”隐藏,得绕过这个静态机制,改用访问器或输出前过滤 别在控制器里临时赋值
$model->hidden
,那是徒劳 用
append
+ 访问器模拟条件性字段隐藏 核心思路:不靠
hidden
,而是把敏感字段全设为
protected
,只通过访问器暴露——访问器内部读配置决定是否返回值。 在模型里定义一个访问器,比如
getPasswordAttr
,里面检查配置
config('api.hide_sensitive')
把字段加进
protected $append = ['password']
,这样
toArray()
才会触发访问器 访问器里写:
return config('api.hide_sensitive') ? null : $value;
,前端拿到的就是
null
或真实值 注意:这种写法对 JSON 输出有效,但
select(['id', 'password'])
仍会查出字段,得配合查询层过滤 查询时用
field()
动态排除字段最干净 如果只是 API 接口需要开关字段,最稳的方式不是动模型,而是在查询那一刻就砍掉不需要的列。 统一在基类控制器或中间件里读取权限/环境配置,比如
$hideFields = config('api.hidden_fields', [])
构造查询时:
UserModel::field(array_diff($allFields, $hideFields))->select()
别用
->hidden(['password'])
链式调用——ThinkPHP 6+ 的
hidden()
方法只影响后续的
toArray()
,不影响 SQL 查询,容易误以为“已过滤”,其实数据库还在查 性能上更优:少查字段,减少网络传输和内存占用 配置驱动的字段白名单比黑名单更可控 依赖
hidden
是黑名单思维,一漏就泄露;换成白名单(
visible
),默认一个字段都不吐,显式声明才给,安全边界更清晰。 PHP 8.5.5 PHP 8.5.5 是 PHP 8.5 分支的维护更新版本。该版本延续了“小步快跑”的迭代逻辑,通过深度错误修复、底层性能微调以及安全加固,旨在为开发者提供一个更健壮、更高效的运行环境。该版本严格遵守语义化版本规范,不包含破坏性变更。 下载 立即学习 “ PHP免费学习笔记(深入) ”; 模型里删掉
$hidden
,改用
protected $visible = ['id', 'username', 'avatar']
不同场景配不同白名单:API V1 用
api_v1_visible
,管理后台用
admin_visible
动态切换只需
$model->visible($config['visible_fields'])
,这个方法是运行时生效的 注意:若模型用了
with()
关联,关联模型也得各自配
$visible
,不会自动继承父级配置 真正麻烦的从来不是“怎么写代码”,而是字段权限要随角色、环境、接口版本甚至请求头参数变化——这时候光靠模型属性扛不住,得在查询构建器或资源转换层做路由级拦截。别省那几行代码,该分层就得分层。

相关文章