获取器方法名由数据库字段转驼峰并加get和Attr构成,如create_time→getCreateTimeAttr;必须public、仅属性访问触发、toArray()会调用,修改器同理且需避免循环调用。

获取器和修改器不是“可选装饰”,而是模型字段行为的声明式契约——写错命名、漏掉类型声明或混用空值处理,就会导致数据在读写链路中悄然失真。
getCreateTimeAttr 这类方法名怎么生成?
字段名必须转驼峰,且严格区分大小写。数据库字段 create_time → 获取器方法名是 getCreateTimeAttr,不是 getCreatetimeAttr 或 getCreate_timeAttr。
- 下划线分隔的字段(如
user_name)→getUserNameAttr - 全小写无下划线(如
id)→getIdAttr,不能省略 - 带数字的(如
order_no)→getOrderNoAttr,不是getOrdernoAttr - 方法必须是 public,否则框架不识别
为什么写了 getSexAttr 却没触发?
常见原因不是语法错,而是调用方式不对或模型未加载成功。
- 用
$model->getData('sex')会绕过获取器,返回原始值 - 用
$model['sex'](数组访问)也不触发,只支持对象属性访问$model->sex - 如果模型继承了自定义基类,确认基类没重写
__get或屏蔽了获取器逻辑 -
toArray()和toJson()会触发,但toRawArray()不会
setAttr 方法里能改其他字段吗?
可以,但必须显式调用 $this->setAttr('other_field', $value),不能直接赋值 $this->other_field = $value。
立即学习“PHP免费学习笔记(深入)”;
- 直接赋值不会走修改器,也不会被自动写入数据库
- 例如
setUpdateTimeAttr中想同步更新update_by,就得写$this->setAttr('update_by', $uid) - 若被修改字段自身也有修改器(如
setUpdateByAttr),它会正常触发 - 避免循环:不要在
setAAttr里调$this->setAttr('a', ...),会死循环
JSON 字段不自动 decode 怎么办?
ThinkPHP 5.1+ 要求必须在模型中声明 $type,光写 getInfoAttr 没用。
- 错误写法:
public function getInfoAttr($value) { return json_decode($value, true); }——$value此时已是数组,再 decode 会出错 - 正确写法:先加声明
protected $type = ['info' => 'json'];,再补获取器处理空值或默认结构 - 若字段允许为 NULL,
getInfoAttr开头要判空:if (null === $value || '' === $value) return []; - 修改器同理,
setInfoAttr接收的是 PHP 数组,需return json_encode($value, JSON_UNESCAPED_UNICODE);
最易被忽略的一点:获取器返回值一旦是对象(如 Carbon 实例),后续序列化时若没定义 JsonSerializable 或 toArray 方法,toJson() 可能抛异常或输出空对象。



















