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

时间:2013-07-04 13:53:37

标签: php laravel laravel-4 eloquent

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

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

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

是否有内置的方法将记录添加到数据透视表中,只有当它还不存在时才会存在?

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

6 个答案:

答案 0 :(得分:221)

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

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

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

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

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

答案 1 :(得分:69)

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

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

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

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

答案 2 :(得分:2)

@alexandre Butynsky方法效果很好但是使用了两个sql查询。

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

要仅使用一个查询,请使用此选项:

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

答案 3 :(得分:0)

尽管所有这些答案都是因为我已经尝试了所有这些答案,但有一件事仍然没有得到解决或者没有处理:更新先前检查的值的问题(取消选中复选框[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);
}

答案 4 :(得分:0)

您可以使用

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

从Laravel 5.7开始:

  

同步关联   您也可以使用sync方法构造多对多关联。 sync方法接受ID数组放置在中间表上,任何不在给定数组中的ID将从中间表中删除。因此,完成此操作后,中间表中将仅存在给定数组中的ID:

答案 5 :(得分:0)

已经发布了一些很好的答案。我也想把这个扔出去。

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

它仅检索当前组合的条目(实际上仅检索id),如果不存在,则将其附加。 sync方法(即使不分离也可以)检索所有当前附加的ID。对于迭代次数较少的较小集合,这几乎没有什么不同,……您明白我的意思。

无论如何,它绝对不那么可读,但是可以解决问题。

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