115

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

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

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

是否有一种内置方法可以仅在不存在的情况下将记录添加到数据透视表?

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

4

5 回答 5

298

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

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

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

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

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

于 2014-04-05T19:11:50.113 回答
81

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

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

或者/并且您可以在数据库中添加唯一性条件,它会在尝试保存双峰时抛出异常。

您还应该看看 Barryvdh 提供的更直接的答案。

于 2013-07-04T18:35:55.463 回答
2

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

一个用于检查购物车是否包含该项目,另一个用于保存。

要仅使用一个查询,请使用以下命令:

try {
    $cart->items()->save($newItem);
}
catch(\Exception $e) {}
于 2014-02-25T15:45:40.493 回答
1

已经发布了一些很棒的答案。不过,我也想把这个扔在这里。

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

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

无论如何,它绝对不那么可读,但它确实有效。

if (is_null($book->authors()->find($author->getKey(), [$author->getQualifiedKeyName()])))
    $book->authors()->attach($author);
于 2018-11-26T22:33:19.327 回答
1

与所有这些答案一样好是因为我已经尝试了所有这些,但有一件事仍未得到解答或没有得到解决:更新先前选中的值的问题(未选中复选框[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);
}
于 2017-10-06T00:40:58.270 回答