必须将 $appends 声明为 public,否则字段不会出现在 API 返回的 JSON 中;访问器命名须严格匹配驼峰规则(如 getFullNameAttribute);append() 用于接口级动态追加,需配合 makeVisible() 使用;API Resource 中 $appends 不生效,须手动在 toArray() 中调用。

$appends 必须是 public,否则字段直接消失
模型里写 $appends = ['full_name'],但 API 返回的 JSON 里压根没这个字段?大概率是把它声明成了 protected $appends 或者漏写了。Laravel 不报错,也不警告,就默默跳过。必须写成:
public $appends = ['full_name'];- 对应访问器方法名是
getFullNameAttribute()(驼峰),不能是getFullnameAttribute()或get_full_nameAttribute() - 如果字段名是
is_admin,访问器就得叫getIsAdminAttribute(),少一个字母或大小写错,toArray()就不调用它 - 别在访问器里写
return $this->attributes['is_admin'] ?? false;——这不是追加,这是读原始字段;追加字段应该是计算出来的、非数据库存的值
append() 比改 $appends 更适合接口级控制
你只在用户详情页需要 can_refund 字段,但订单列表页不需要?硬塞进 $appends 会导致所有地方都多传一个字段,浪费带宽,还可能暴露敏感逻辑。这时候该用实例方法 append():
-
$order->append(['can_refund'])->toArray()—— 只影响当前实例 -
Order::all()->append(['can_refund'])—— 作用于整个集合(注意:必须是Collection,不能是 Builder,Order::where(...)->append(...)->get()会报错) -
append()内部只是临时合并进当前实例的追加列表,不影响模型类定义,也不会污染其他请求 - 如果字段本身被
$hidden拦住了,append()也救不回来;得先makeVisible(['can_refund']),再append(),顺序不能反
API Resource 里 $appends 不自动生效
用了 JsonResource 封装响应?那恭喜,模型里的 $appends 完全不起作用。Resource 是独立转换层,它不会自动读取模型的追加配置。
- 必须手动在 Resource 的
toArray()里写:'full_name' => $this->full_name - 别在 Resource 里重复实现逻辑,比如又写一遍拼接 first_name + last_name——访问器已经写了,这里只负责“转发”
- 如果字段依赖当前用户(比如
is_favorited),不要在模型访问器里调auth()->id(),而应在 Resource 构造时传参,或用with()注入上下文 - Resource 中调
$this->full_name会触发模型访问器,所以性能问题(如 N+1)依然存在,该预加载的还得预加载
真正容易被忽略的是:访问器执行时机和缓存干扰。比如你在中间件里设置了全局状态,但模型序列化发生在响应生成阶段,此时访问器拿到的可能是旧的 auth 实例或空 session。动态逻辑别塞进模型,优先收口到 Resource 或控制器层。


















