You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 07:03:31