Laravel Observer依赖注入异常:整数属性变为字符串类型
Laravel 11 + Filament:Observer中模型整数属性被转为字符串的问题分析
问题场景
在Laravel 11与Filament框架环境下,Payment模型的created事件Observer中,注入的$payment实例里,amount、days_added这类定义为整数类型的数据库字段,实际呈现为字符串类型。尝试通过模型的**属性转换(Attribute Casting)**配置未解决问题,最终调用refresh()方法重新从数据库拉取数据后,属性恢复为预期的整数类型。
相关代码
Payment Observer代码
class PaymentObserver implements ShouldHandleEventsAfterCommit { /** * 处理Payment的"created"事件。 */ public function created(Payment $payment): void { $payment->refresh(); // 调用refresh()后属性恢复为整数类型 $barbershop = Barbershop::find($payment->barbershop_id); $barbershop->status = BarbershopStatusEnum::ACTIVE; $barbershop->expired_date = Carbon::now()->addDays($payment->days_added); $barbershop->save(); } }
Filament创建Payment的Action代码
->action(function(Barbershop $barbershop, array $data){ try{ $data['user_id'] = Auth::user()->id; $barbershop->payments()->create($data); Notification::make()->title('Saved successfully')->success()->send(); }catch(Exception $e){ Notification::make()->title('Save Failed! ' . $e->getMessage())->danger()->send(); } })
原因分析
- Filament表单输入特性:Filament表单提交的数值类输入默认以字符串类型传递到
$data数组中,当通过create($data)创建模型时,Laravel会直接将这些字符串值赋值给模型属性,此时模型实例的属性值保留了原始输入的类型。 - 属性转换触发时机:模型的
$casts配置通常在从数据库读取数据或显式调用属性访问器时生效。刚创建的模型实例(未调用refresh())的属性值来自提交的原始数据,并未经过数据库返回值的类型转换,因此即使配置了属性转换,也可能未触发类型转换逻辑。 - refresh()的作用:调用
refresh()会重新从数据库查询该模型记录,此时数据库返回的整数类型字段会被Laravel自动转换为PHP整数类型,从而修正属性类型不符的问题。
结论
该问题并非框架Bug,而是业务代码与框架特性的适配问题:
- 若已配置模型属性转换但未生效,需检查
$casts配置是否正确(例如确认字段名拼写、类型是否匹配); - 若表单输入的字符串类型值未被模型转换,可在Filament表单层对字段设置类型约束(例如使用
numeric()规则),或在创建模型前手动转换$data中的数值类型; - 调用
refresh()是快速解决问题的方案,但本质是通过重新拉取数据库数据来修正属性类型。
内容的提问来源于stack exchange,提问作者Junaris Alf
相关产品推荐
相关产品推荐

