首页 文章

阻止Laravel将多个记录添加到数据透视表

提问于
浏览
74

我有多对多的关系设置和工作,将项目添加到我使用的购物车:

$cart->items()->attach($item);

这会将项目添加到数据透视表中(应该如此),但如果用户再次单击链接以添加他们已添加的项目,则会在数据透视表中创建重复项 .

是否有内置的方法将记录添加到数据透视表只有一个尚不存在?

如果没有,我如何检查数据透视表以查找是否已存在匹配的记录?

6 回答

  • 0

    您可以通过编写一个非常简单的条件来检查现有记录的存在:

    if (! $cart->items->contains($newItem->id)) {
        $cart->items()->save($newItem);
    }
    

    或者/并且您可以在数据库中添加unicity条件,它会在尝试保存doublet时抛出异常 .

    您还应该看看下面Barryvdh的更简单的答案 .

  • 2

    您还可以使用 $model->sync(array $ids, $detaching = true) 方法并禁用分离(第二个参数) .

    $cart->items()->sync([$item->id], false);
    

    更新:从Laravel 5.3或5.2.44开始,您还可以调用syncWithoutDetaching:

    $cart->items()->syncWithoutDetaching([$item->id]);
    

    哪个完全相同,但更具可读性:)

  • 0

    @alexandre Butynsky方法工作得很好,但使用两个SQL查询 .

    一个用于检查购物车是否包含物品和一个要保存的物品 .

    要仅使用一个查询,请使用:

    try {
        $cart->items()->save($newItem);
    }
    catch(\Exception $e) {}
    
  • 200

    尽管所有这些答案都是因为我已经尝试了所有这些答案,但有一件事仍然没有得到解决或者没有处理:更新先前检查的值的问题(取消选中复选框[es]) . 我确实有类似于上述问题的内容,我希望在产品功能表(数据透视表)中检查和取消选中产品的功能 . 我是一个新手,我已经意识到以上都没有这样做 . 添加新功能时都很好,但是当我想删除现有功能时(即取消选中)

    我将不胜感激任何启示 .

    $features = $request->get('features');
    
    if (isset($features) && Count($features)>0){
        foreach ($features as $feature_id){
            $feature = Feature::whereId($feature_id)->first();
            $product->updateFeatures($feature);
        }
    }
    
    //product.php (extract)
    public function updateFeatures($feature) {
            return $this->features()->sync($feature, false);
    }
    

    要么

    public function updateFeatures($feature) {
       if (! $this->features->contains($features))
            return $this->features()->attach($feature);
    }
    //where my attach() is:
    public function addFeatures($feature) {
            return $this->features()->attach($feature);
    }
    

    对不起,伙计们,我不确定是否应该删除这个问题,因为我自己找出了答案,这听起来有点愚蠢,上面的答案就像工作@Barryvdh sync()一样简单如下;阅读越来越多关于:

    $features = $request->get('features');
    if (isset($features) && Count($features)>0){
        $product->features()->sync($features);
    }
    
  • 0

    你可以使用

    $cart->items()->sync($items)

    从Laravel 5.7开始:

    同步关联您还可以使用sync方法构建多对多关联 . sync方法接受要放在中间表上的ID数组 . 将从中间表中删除不在给定数组中的任何ID . 因此,在此操作完成后,只有给定数组中的ID将存在于中间表中:

  • 62

    已经发布了一些很棒的答案 . 我想把这个扔出去 .

    来自@AlexandreButynski和@Barryvdh的答案比我的建议更具可读性,这个答案增加了一些效率 .

    它只检索当前组合的条目(实际上只检索id),如果它不存在则仅附加它 . 同步方法(即使没有分离)检索所有当前附加的ID . 对于具有少量迭代的较小集合,这几乎没有区别,...你明白我的意思 .

    无论如何,它绝对不是可读的,但它可以解决问题 .

    if (is_null($book->authors()->find($author->getKey(), [$author->getQualifiedKeyName()])))
        $book->authors()->attach($author);
    

相关问题