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

Laravel Filament:计算Repeater中所有商品总价并存入数据库

解决Laravel Filament中Repeater组件订单总价计算并存库问题

问题分析

你当前的代码仅能计算单个Repeater项的金额,且无法将所有商品的总价存入orders表的total_amount字段,核心问题在于没有遍历所有Repeater条目计算总和,也未在表单提交流程中正确将总和赋值给订单模型的对应属性。

解决方案

步骤1:修改表单,添加实时总价显示(可选,提升用户体验)

在Repeater组件外部添加一个只读字段,通过live()和reactive()实时计算所有商品的总价:

Forms\Components\Grid::make()->schema([
    // 原有Repeater组件
    Forms\Components\Repeater::make('items')
        ->relationship()
        ->required()
        ->label(false)
        ->addActionLabel('Add product')
        ->schema([
            Select::make('product_id')
                ->options(Product::all()->pluck('name', 'id'))
                ->label('Product')
                ->reactive()
                ->searchable()
                ->required()
                ->columnStart(1)
                ->afterStateUpdated(function ($state, Set $set) {
                    $set('unit_price', Product::find($state)?->price ?? 0);
                }),
            TextInput::make('unit_price')->columnStart(2)->readOnly(),
            TextInput::make('qty')
                ->numeric()
                ->default(1)
                ->minValue(1)
                ->required()
                ->live()
                ->reactive()
                ->dehydrated()
                ->columnStart(3),
        ])->columnSpan('full'),

    // 添加总价显示字段
    Forms\Components\TextInput::make('total_amount')
        ->label('Total Amount')
        ->readOnly()
        ->live()
        ->reactive()
        ->default(function (Get $get) {
            $items = $get('items') ?? [];
            return collect($items)->sum(function ($item) {
                return ($item['qty'] ?? 0) * ($item['unit_price'] ?? 0);
            });
        }),
])

步骤2:表单提交时自动计算并赋值总价

在Filament的Form组件中添加beforeSave回调,遍历所有订单条目计算总和,赋值给订单模型的total_amount字段:

// 在你的CreateOrderForm/EditOrderForm的form()方法末尾追加
->beforeSave(function (Order $record, array $data) {
    $total = collect($data['items'])->sum(function ($item) {
        return ($item['qty'] ?? 0) * ($item['unit_price'] ?? 0);
    });
    $record->total_amount = $total;
})

备选方案:用模型事件自动计算(更通用)

如果希望在任何场景下创建/更新订单都自动计算总价,可以在Order模型中注册saving事件:

// app/Models/Order.php
protected static function boot()
{
    parent::boot();

    static::saving(function (Order $order) {
        $order->total_amount = $order->items->sum(function ($item) {
            return $item->qty * $item->unit_price;
        });
    });
}

注意:使用模型事件前,需确保订单与订单条目的关联关系已正确定义:

// Order模型中添加关联方法
public function items()
{
    return $this->hasMany(OrderItem::class);
}

关键注意事项

  • 确保Order模型的$fillable数组包含total_amount字段,否则无法正常赋值:
    // app/Models/Order.php
    protected $fillable = ['number', 'customer_id', 'total_amount'];
    
  • 实时总价显示依赖live()和reactive(),能让用户操作时看到动态变化的金额
  • 表单beforeSave回调仅在Filament后台操作时生效,模型事件则覆盖所有订单创建/更新场景

内容的提问来源于stack exchange,提问作者Ivan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 14:03:14