Php Laravel避免子表中的重复条目

Php Laravel避免子表中的重复条目,php,laravel,Php,Laravel,我有很多条形码的产品,当我在产品编辑页面中添加/删除/编辑产品的条形码时,它会再次保存条形码(PS:我知道问题的来源,但不确定解决方案) 逻辑 因此,当我在产品编辑页面中时,我希望发生以下情况: 如果当前条形码已更改,请更新它们 如果删除了任何当前条形码,请将其从数据库中删除 如果列表中添加了任何新条形码,请将其添加到数据库中 基本上是我正在寻找的sync()功能,但基于我的模型关系,我认为使用sync()不是一个选项 代码 产品型号 public function barcodes() {

我有很多条形码的产品,当我在产品编辑页面中添加/删除/编辑产品的条形码时,它会再次保存条形码(PS:我知道问题的来源,但不确定解决方案)

逻辑 因此,当我在产品编辑页面中时,我希望发生以下情况:

  • 如果当前条形码已更改,请更新它们
  • 如果删除了任何当前条形码,请将其从数据库中删除
  • 如果列表中添加了任何新条形码,请将其添加到数据库中
  • 基本上是我正在寻找的
    sync()
    功能,但基于我的模型关系,我认为使用
    sync()
    不是一个选项

    代码
    产品型号

    public function barcodes()
    {
        return $this->hasMany(Barcode::class, 'product_id', 'id');
    }
    
    protected $fillable = [
        'product_id', 'serial_number',
    ];
    
    public function product()
    {
        return $this->belongsTo(Product::class);
    }
    
    条形码型号

    public function barcodes()
    {
        return $this->hasMany(Barcode::class, 'product_id', 'id');
    }
    
    protected $fillable = [
        'product_id', 'serial_number',
    ];
    
    public function product()
    {
        return $this->belongsTo(Product::class);
    }
    
    控制器(更新功能)

    正如我前面提到的
    我知道问题的来源,但不确定它的解决方案
    ,重复保存数据的问题是我正在使用
    $barcode=new barcode

    额外的 为了清楚起见,当我向后端发送更新请求时,我的数据就是这样的

    问题:
    为了实现所需的逻辑,我应该在代码中更改什么?

    我认为这是因为当数据发送到服务器时,它们也包含旧数据

    这段代码总是创建一个新代码,而不更新它

    $barcode=新条码;
    .
    .
    .
    $barcode->save();
    
    也许你可以这样做

    foreach($request->input('barcode')作为$bb)
    {
    如果(!empty($bb['serial_number']){//请确保不保存空值
    /*更新具有序列号的行或创建一个序列号*/
    条形码::更新或创建([
    “序列号”=>$bb[“序列号”]//如果序列号是唯一的。
    “产品id”=>$product->id
    ], [ 
    “序列号”=>$bb[“序列号”],
    “产品id”=>$product->id,
    ]);
    }
    }
    
    使用序列号查找条形码并进行更新。 未找到条形码时,创建新条形码


    希望这能有所帮助。

    我就是这样为一对多关系创建同步功能的:

    public function update(Request $request, $id)
    {
        $product = Product::find($id);
        $product->name = $request->input('name');
        if($product->save())
        {
            if(!empty($request->input('barcodes')))
            {
                $barcodeSync = []; // We will use this to save all the barcode id's that exist in the database.
                foreach($request->input('barcodes') as $bb)
                {
                    if(!empty($bb['serial_number'])){
                        $barcode = $product->barcodes()->updateOrCreate(
                            ['id' => $bb['id'] ?? 0],
                            ['serial_number' => $bb['serial_number']]
                        ); // This will create a new barcode for the product if that barcode doesn't exist yet or update the existing barcode using it's id.
                        array_push($barcodeSync, $barcode->id); // This will add the id to the array of existing barcodes for this product.
                    }
                }
                $product->barcodes()->whereNotIn('id', $barcodeSync)->delete(); //Deletes all barcodes for this product that were not in the request.
            }
        }
    }
    
    这应该解决你的3个期望

  • 这将更新与“id”和“产品id”匹配的任何条形码。(请注意,如果“序列号”不变,laravel实际上不会更新模型)

  • 它将为产品创建或更新的所有条形码保存在
    $barcodeSync
    数组中,以便您以后可以删除请求中不再存在的所有条形码
    $product->barcodes()->whereNotIn('id',$barcodeSync)->delete()

  • 它将创建传入请求的任何新条形码,因为新条形码在请求中没有“id”字段,它将查询id为0(0将不存在),这将触发创建新条形码并将其分配给产品。(为此,还应确保条形码模型的“id”字段不在
    $filleble
    数组中,因为它会在每次创建新条形码时尝试将id设置为0,这将导致错误)


  • 希望这对你有帮助

    如果您是sql数据库,我建议您在数据库上放置复合键。然后是用户insertOrUpdate方法。注意这个!您的
    updateOrCreate()
    方法可以更新另一个产品的条形码模型,并可以将其产品更改为当前产品。您应该按id和product_id进行查询,以免意外更改实际上不属于该产品的条形码。@RobertKujawa Hi。你说得很对!现在我修复代码。谢谢你的评论!谢谢,我会测试你的代码并告诉你结果。