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

Laravel中选择多个产品时如何为单ticket存储多条product_ticket记录

解决方案

第一步:调整表单提交结构

首先需要把表单的产品相关字段改为数组格式,确保每个选中的产品对应独立的product_id、serial_number、quantity参数,示例表单结构如下:

<!-- 多产品输入组示例,新增产品时重复该结构即可 -->
<div class="product-item">
  <input type="checkbox" name="products[][product_id]" value="1">
  <input type="text" name="products[][serial_number]" placeholder="对应产品序列号">
  <input type="number" name="products[][quantity]" value="1" min="1">
</div>
<div class="product-item">
  <input type="checkbox" name="products[][product_id]" value="2">
  <input type="text" name="products[][serial_number]" placeholder="对应产品序列号">
  <input type="number" name="products[][quantity]" value="1" min="1">
</div>

提交后$request->products会返回二维数组,每个子项对应一个选中产品的全部参数。

第二步:修改控制器store逻辑

提供两种实现方案按需选择:

方案1:批量插入(性能更优)

通过关联关系的createMany方法一次性创建所有中间表记录,代码如下:

public function store(Request $request)
{
    // 参数校验,建议加上避免非法数据入库
    $validated = $request->validate([
        'contact_id' => 'required|exists:contacts,id',
        'statusTicket_id' => 'required|exists:status_tickets,id',
        'typeTicket_id' => 'required|exists:type_tickets,id',
        'products' => 'required|array',
        'products.*.product_id' => 'required|exists:products,id',
        'products.*.serial_number' => 'required|string',
        'products.*.quantity' => 'required|integer|min:1',
    ]);

    // 创建Ticket主记录
    $ticket = new Ticket();
    $ticket->contact_id = $validated['contact_id'];
    $ticket->statusTicket_id = $validated['statusTicket_id'];
    $ticket->typeTicket_id = $validated['typeTicket_id'];
    $ticket->idOwner = Auth::user()->id;     
    $ticket->save();

    // 补全所有中间表记录需要的ticket_id
    $productTickets = collect($validated['products'])->map(function ($item) use ($ticket) {
        $item['ticket_id'] = $ticket->id;
        return $item;
    })->toArray();

    // 批量创建关联记录
    $ticket->productXticket()->createMany($productTickets);

    Session::flash('success');
    return redirect()->route('tickets.view');
}

方案2:循环单条插入(适合单条记录需单独处理的场景)

如果需要对每个产品的关联记录做单独逻辑判断,可以用循环逐行创建:

// 省略前面Ticket创建和参数校验代码
foreach ($validated['products'] as $productItem) {
    $productXticket = new ProductXTicket();
    $productXticket->ticket_id = $ticket->id;
    $productXticket->product_id = $productItem['product_id'];
    $productXticket->serial_number = $productItem['serial_number'];
    $productXticket->quantity = $productItem['quantity'];
    $productXticket->save();
}

可选实现:用多对多关联的attach方法

你已经在Ticket模型中定义了products的多对多关联,也可以直接操作关联,不需要手动实例化中间表模型:

// 处理成attach方法要求的格式:键为product_id,值为中间表额外字段数组
$attachData = collect($validated['products'])->mapWithKeys(function ($item) {
    return [
        $item['product_id'] => [
            'serial_number' => $item['serial_number'],
            'quantity' => $item['quantity']
        ]
    ];
})->toArray();

$ticket->products()->attach($attachData);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 13:06:05