ThinkPHP 5.1中通过模型获取器(getAttr)实现状态映射、时间格式化和虚拟字段拼接;支持withAttr动态覆盖及getData获取原始值。

你想在ThinkPHP 5.1中让数据库里的数字状态自动变成“正常”“禁用”这类可读文字,而不是每次都在控制器里手动写数组映射;你想把时间戳字段直接输出为“2024-05-20”格式,又不想丢失原始数值用于后续排序或计算;你想定义一个不存在于数据表的虚拟字段(比如 fullname),让它在模型转数组时自动拼接 first_name 和 last_name —— 这些都不是靠模板里反复 if-else 或 foreach 解决的,而是模型获取器(getAttr)的职责范围。
定义基础获取器
在模型类中添加一个 public 方法,方法名必须是 get + 字段名驼峰 + Attr,例如 status 字段对应 getStatusAttr。
方法接收两个参数:第一个 $value 是该字段从数据库读出的原始值,第二个 $data 是当前模型实例的全部原始数据数组(可用于跨字段计算)。
在 User.php 模型中写:
public function getStatusAttr($value) {
$status = [-1 => '删除', 0 => '禁用', 1 => '正常', 2 => '待审核'];
return $status[$value] ?? '未知';
}
【$value 可能为 null 或空字符串,务必做兜底处理】
定义虚拟字段获取器
虚拟字段不对应真实数据库列,但你仍希望它像真实字段一样被访问和序列化。
第一步:在模型类顶部声明该属性占位,例如 protected $fullname;
第二步:定义获取器方法,命名必须严格匹配字段小写形式,即 getFullnameAttr(注意不是 getFullNameAttr)。
第三步:方法体内使用 $data 参数取值拼接:
public function getFullnameAttr($value, $data) {
return $data['first_name'] . ' ' . $data['last_name'];
}
第四步:查询时显式调用 append(['fullname']),否则 toArray() 不会触发该获取器。
动态覆盖获取器(withAttr)
方法一:单字段临时覆盖
User::withAttr('email', function($value) { return strtolower($value); })->select();
方法二:多字段批量设置
User::withAttr('status', function($v) { return ['0'=>'停用','1'=>'启用'][$v] ?? $v; })
->withAttr('create_time', function($v) { return date('Y-m-d', $v); })
->select();
【withAttr 必须放在 select()/all()/find() 之前,且之后不能再链式调用 where 等模型查询方法】
获取原始值(绕过获取器)
第一步:直接访问模型属性时,获取器自动生效,例如 $user->status 返回的是中文文本。
第二步:要拿到数据库原始数字,改用 getData() 方法:
echo $user->getData('status'); // 输出 1
第三步:要一次性获取全部原始字段(不含获取器处理结果),直接调用无参 getData:
dump($user->getData());
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











