yii 2 active record 通过重写 fields() 控制 toarray() 默认输出字段(如隐藏 password_hash),用 extrafields() 管理关联数据扩展字段,并支持权限动态过滤。

Yii 2 的 Active Record 模型默认调用 toArray() 会把所有公开属性(包括数据库字段、虚拟属性、关联对象等)转为数组。若需隐藏某些敏感或冗余字段(如 password_hash、auth_key、created_at 等),不能靠前端过滤或手动 unset,而应通过模型层统一控制——核心方式是重写 fields() 和/或 extraFields() 方法。
只保留白名单字段:重写 fields()
该方法定义 toArray() 默认输出的字段集合。返回一个键值数组,键为输出字段名,值为对应属性名或闭包。
- 不声明的字段不会出现在结果中,天然实现“隐藏”
- 可返回
parent::fields()再 unset 特定项,也可全新定义 - 示例:隐藏密码相关字段和时间戳
{
$fields = parent::fields();
unset($fields['password_hash'], $fields['auth_key'], $fields['password_reset_token']);
return $fields;
}
按需扩展额外字段:重写 extraFields()
该方法用于支持 toArray(['id', 'name'], ['profile']) 中的第二个参数(即显式请求的扩展字段)。它不影响默认输出,但可用来安全暴露关联数据。
- 常用于控制关联模型是否加载、是否过滤其内部字段
- 例如只允许输出
profile关联中的nickname和avatar,不暴露user_id或updated_at
{
return [
'profile' => function () {
return $this->profile ? $this->profile->toArray(['nickname', 'avatar']) : null;
},
];
}
配合场景:API 输出与序列化控制
在 RESTful 接口或 JSON 返回中,建议结合 Serializer 或控制器层统一处理,避免每个地方重复逻辑。
- 控制器中可直接调用
$model->toArray(['id', 'username', 'email'])指定字段子集 - 若使用
yii\rest\Serializer,它会自动调用fields();你只需确保模型已正确定义 - 注意:
hidden属性(Laravel 风格)在 Yii 2 中不存在,不可直接设置public $hidden = [...]
进阶:动态字段控制(如角色权限)
若需根据当前用户权限决定是否输出某字段(如管理员可见 last_login_ip,普通用户不可见),可在 fields() 中加入运行时判断:
- 检查
Yii::$app->user->can('viewIp')或类似授权逻辑 - 字段值可为闭包,实现懒计算与条件过滤
{
$fields = parent::fields();
if (!Yii::$app->user->can('admin')) {
unset($fields['last_login_ip'], $fields['login_count']);
}
return $fields;
}











