$hidden仅在模型序列化为数组或JSON时生效,不干预数据库查询、访问器逻辑及字段读写;常见失效原因包括字段名大小写错误、访问器返回字段不受控、append字段绕过隐藏、关联模型需单独设置$hidden,且$visible优先级高于$hidden。

ThinkPHP6.0模型中$hidden不起作用,核心原因是它只在模型“序列化为数组或JSON”时生效,而**不参与数据库查询、不拦截访问器逻辑、也不影响字段读写行为**。很多问题表面是$hidden失效,实则是对它的作用边界理解偏差。
字段仍在toArray()/toJson()中出现
这是最常见现象,原因有三:
-
字段名大小写或拼写错误:数据库列是
user_name,但$hidden = ['username']就无效;Linux服务器严格区分大小写,必须完全一致 -
访问器(Getter)返回的字段不受$hidden控制:比如定义了
getFullnameAttr(),即使fullname不在数据库里、也没写进$hidden,toArray()仍会包含它——因为访问器被视为“动态计算字段”,默认开放 -
用了append()追加的字段,未被$hidden覆盖:append字段默认也绕过
$hidden,如需隐藏,得在append()前手动过滤,或改用visible()白名单兜底
数据库查出来的字段没被隐藏
$hidden根本不会修改SQL查询语句。它只在模型实例转成数组时做键过滤。所以:
-
UserModel::find(1)查出的数据对象,$user->password依然能直接读取(只是$user->toArray()里不出现) - 如果控制器里写了
return json($user),等价于json($user->toArray()),这时$hidden才起效 - 若误用
Db::table('user')->find()直查,模型层完全不介入,$hidden自然无效
关联模型字段被误以为该隐藏
$hidden只作用于当前模型的原始字段,对with('profile')这类关联数据毫无影响:
立即学习“PHP免费学习笔记(深入)”;
- 想隐藏关联模型里的
phone,必须在ProfileModel里单独定义$hidden = ['phone'] -
$hidden = ['profile.phone']写法无效,ThinkPHP不支持点号嵌套语法 - 关联数据默认全量返回,建议在关联模型中统一设
$visible或$hidden,而非主模型中硬控
visible与hidden同时存在却没效果
两者互斥,$visible优先级永远高于$hidden:
- 若模型中同时写了
$visible = ['id', 'nickname']和$hidden = ['password', 'email'],最终只返回id和nickname,其余全部过滤 - 空数组
$visible = []表示“不返回任何字段”,不是“恢复全部”,容易引发接口空响应 - 动态调用
$user->visible(['id'])->toArray()会覆盖模型级$visible和$hidden,适合API参数驱动场景



















