动态添加序列化属性必须用 append()、makeVisible() 或访问器组合,直接赋值或修改 $appends 无效;append() 仅适用于 Collection 实例且需小写蛇形命名;makeVisible() 为实例级操作,须在 toArray() 前调用;访问器中禁止 N+1 查询,纯计算字段可放心使用;原始字段值应通过 getRawOriginal() 获取。

动态添加属性不能靠直接赋值或改写 $appends,必须用 append()、makeVisible() 或访问器组合控制序列化行为;否则字段不会出现在 toArray()/toJson() 结果里。
append() 是运行时追加访问器属性的唯一可靠方式
你定义了 getIsFavoritedAttribute(),也写了 $appends = ['is_favorited'],但只想在某个接口里暴露它?删掉 $appends,改用 append()。
-
append()只能作用于 Eloquent Collection 实例(即get()之后),不能用在查询构造器上(where()->append()->get()会报错) - 传参支持字符串或数组:
$models->append('permissions')或$models->append(['permissions', 'full_name']) - 名称必须小写蛇形,Laravel 自动映射到
getPermissionsAttribute()—— 写成getpermissionsAttribute()或getPermissionAttribute()都不生效 - 如果 accessor 返回
null,toJson()默认会过滤掉该字段;要强制保留,得在 accessor 里兜底:return $value ?? ''
makeVisible() 适合按权限/角色临时暴露隐藏字段
比如 raw_data 只给管理员看,又不想全局放开 —— 这时别碰 $visible,用 makeVisible()。
-
makeVisible()是实例级操作,只影响当前模型,不影响其他实例或类定义 - 必须在
toArray()之前调用,$model->makeVisible(['raw_data'])->toArray()不生效(链式调用顺序问题) - 对集合无效:不能
$collection->makeVisible(...),得用$collection->each(fn ($m) => $m->makeVisible(...)) - 一旦模型已转成数组,再调
makeVisible()完全没用 —— 它只干预后续的序列化过程
访问器里用运行时上下文是安全的,但别查库
getIsFavoritedAttribute() 里调 auth()->id() 或 request()->header('X-Device') 没问题,因为每次读取属性都会执行。但 N+1 就来了。
- 禁止在 accessor 里做单条查询,例如
User::find($this->referrer_id)—— 集合里 100 条就触发 100 次查询 - 正确做法:提前预加载关联(
with('referrer')),然后 accessor 里用$this->referrer?->name - 纯计算字段(如时间格式化、字符串拼接)可放心放 accessor,不耗资源
- 需要原始数据库值时,别用
$model->attributes['field'],用$model->getRawOriginal('field')—— 这是唯一官方保证绕过 accessor 的方式
直接赋值 $model->xxx = 'val' 只是临时属性,不出现在序列化结果中
有人试过 $user->is_admin = true 然后期待它出现在 API 响应里 —— 不会。这不是“动态属性”,只是普通对象属性。
- 这种赋值只存在于当前 PHP 对象生命周期,
toArray()和toJson()完全忽略它 - 若真要临时塞字段进响应,要么用
append()配合访问器,要么在 Resource 的toArray()里手动加键值对 - 想让字段参与 JSON 序列化,它必须是访问器返回的值,并且被
append()或$appends显式声明


















