$casts用于自动类型转换,$appends用于将访问器结果包含在json输出中;二者与所谓“属性守卫”无关,php中无此内置机制,实际可用的是$fillable、$guarded、访问器、修改器等。

什么是 Eloquent 的 $casts 和 $appends,和“属性守卫”根本不是一回事
PHP 中没有叫「Eloquent Attribute Guards」的内置机制——这是常见误解。Laravel 官方文档里从没提过这个术语,社区里偶尔有人用它泛指对模型属性读写做限制的行为,但实际能用的只有 $casts、$fillable、$guarded、访问器(getFooAttribute)、修改器(setFooAttribute)以及 setAttribute 重写等手段。所谓“状态转换条件”,本质是业务逻辑层面对字段赋值或变更的约束,不是框架自带的守卫开关。
如果你在调试时发现某个字段怎么都设不进去,或者改了没反应,大概率是掉进了下面这些坑:
-
$fillable没加该字段,批量赋值(create()/update())直接被忽略 - 用了
$guarded = ['*']却忘了显式放开关键字段 - 字段有访问器但没配
$appends,导致 JSON 输出里看不到,误以为没生效 - 在状态机逻辑里直接改了属性却没调用
save(),或用了forceFill()绕过了$fillable
如何在状态变更时控制字段可写性:用 setAttribute + 状态检查
真正可控的方式,是在模型里重写 setAttribute,结合当前状态做拦截。比如订单模型只允许在 pending 状态下修改收货地址:
public function setAttribute($key, $value)
{
if ($key === 'shipping_address' && $this->status !== 'pending') {
throw new RuntimeException('Cannot modify shipping_address when status is not "pending"');
}
parent::setAttribute($key, $value);
}
注意这里不能只靠前端或控制器判断——必须在模型层硬控,否则 API 或队列任务绕过控制器时就失效了。
- 别在
setAttribute里做复杂查询(比如查关联状态),会拖慢所有赋值操作 - 如果需要兼容批量更新(如
update(['status' => 'shipped'])),还得配合观察者(updating)再校验一次 - 抛异常比静默忽略更安全;静默会导致调用方以为成功,后续逻辑出错更难排查
状态相关字段自动计算:用访问器 + $appends,但别滥用
像 is_shippable、can_cancel 这类衍生状态,适合用访问器定义,再通过 $appends 暴露给 JSON:
protected $appends = ['can_cancel'];
public function getCanCancelAttribute()
{
return in_array($this->status, ['pending', 'confirmed']);
}
这种写法干净,但要注意:
- 访问器返回的是实时计算结果,不会存进数据库,也不能用于
where查询(得用DB::raw或数据库视图) - 如果计算逻辑涉及关联模型(比如
$this->payments->sum('amount')),记得提前load(),否则 N+1 -
$appends里的字段名必须和访问器方法名一致(去掉get和Attribute),大小写敏感
复杂状态流转建议交给专门的状态机包,别手写 if/else
当状态多于 4 种、转移规则超过 2 条,硬编码 if ($from === 'pending' && $to === 'shipped') 很快失控。推荐用 spatie/laravel-model-states 或 ryangjchandler/laravel-state-machine 这类包:
- 状态定义集中,转移规则显式声明,避免漏掉边界情况(比如从
cancelled能否回到pending) - 自带事件钩子(
stateChanging/stateChanged),方便插日志、发通知、校验权限 - 支持条件转移(
when(fn() => $this->payment_received)),比手写判断更易读
自己封装状态逻辑时,最容易被忽略的是并发场景:两个请求同时把状态从 pending 改成 shipped,可能造成重复发货。得加数据库行锁(sharedLock())或乐观锁(版本号字段)来兜底。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











