Laravel 10模型事件中对象类型属性赋值不生效问题
问题解决:Laravel Saving事件中对象类型Cast字段赋值不生效
问题概述
在Laravel 10中使用Cknow/Money包处理金额字段,配置MoneyIntegerCast类型转换后,在saving事件中对refunded_amount赋值时发现完全不生效;类似的,Carbon日期字段在事件内即时查看赋值结果显示旧值,仅保存后刷新模型才会更新(金额字段甚至保存后也无变化)。
核心原因
Laravel的模型属性访问器(包括类型转换逻辑)会缓存转换后的对象结果,直接赋值对象类型属性时,未触发类型转换的设置逻辑,也未正确更新模型的$attributes数组或标记字段为脏,导致赋值操作未被系统识别。
解决方案
1. 针对Money等自定义Cast对象字段
使用setAttribute()方法手动设置属性,该方法会触发类型转换的处理逻辑,同时自动标记字段为脏:
static::saving(function (self $order) { if ($order->refunded_amount->greaterThan($order->total_amount)) { // 用setAttribute替代直接赋值,触发类型转换流程 $order->setAttribute('refunded_amount', $order->total_amount); // 若仍有异常,可手动标记字段为脏 // $order->markAsDirty('refunded_amount'); dd($order->refunded_amount); // 此时会显示正确的赋值结果 } });
2. 针对Carbon日期字段
日期字段保存后会更新,但事件内即时查看显示旧值,是因为访问器缓存了旧的Carbon对象,可通过setAttribute()或清除属性缓存解决:
static::saving(function (self $order) { $order->setAttribute('renewed_at', now()); // 或者用清除缓存的方式 // $order->renewed_at = now(); // unset($order->renewed_at); dd($order->renewed_at); // 现在会显示更新后的时间 });
补充说明
- 直接赋值整数等原生类型字段无问题,是因为这类字段不需要复杂的类型转换逻辑,模型能直接识别变更并同步到
$attributes。 - 若自定义了修改器,需确保其逻辑未干扰类型转换的正常处理流程。
内容的提问来源于stack exchange,提问作者eComEvo
相关产品推荐
相关产品推荐

