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

Al_*_*Al_ 87 php laravel eloquent laravel-4

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

$cart->items()->attach($item);
Run Code Online (Sandbox Code Playgroud)

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

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

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

Bar*_*vdh 242

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

$cart->items()->sync([$item->id], false);
Run Code Online (Sandbox Code Playgroud)

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

$cart->items()->syncWithoutDetaching([$item->id]);
Run Code Online (Sandbox Code Playgroud)

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

  • 这应该被接受作为答案,这是一个比接受的答案更好的方法 (8认同)
  • 对于像我这样的新手:`$ cart-> items() - > sync([1,2,3])`将构造给定数组中的id的多对多关系,`1`,`2`,和`3`,并删除(或"分离")所有其他id不在数组中.这样,只有数组中给出的id将存在于表中.Brilliant @Barryvdh使用未记录的第二个参数来禁用该分离,因此不会删除不在给定数组中的关系,但只会附加唯一的ID.[查看"同步续订"文件.(Laravel 5.2)](https://laravel.com/docs/5.1/eloquent-relationships#many-to-many) (4认同)
  • 仅供参考,我更新了文档,因此5.2及以上版本:https://laravel.com/docs/5.2/eloquent-relationships#inserting-many-to-many-relationships泰勒立即添加了`syncWithoutDetaching()`,其中调用了sync()与false作为第二个参数. (3认同)
  • 防止分离未列出的ID的第二个布尔参数不在主L5文档中.很高兴知道 - 似乎是在一个声明中"附加(如果尚未附加")的唯一方法. (2认同)

Ale*_*ski 70

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

if (! $cart->items->contains($newItem->id)) {
    $cart->items()->save($newItem);
}
Run Code Online (Sandbox Code Playgroud)

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

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

  • 我不喜欢这个解决方案,因为它强制一个额外的查询($ cart-> items)我一直在做类似的事情:`$ cart-> items() - > where('foreign_key',$ foreignKey) - > count ()`其实,实际上也执行了额外的查询'^^但是我不需要获取和保存整个集合,除非我真的需要它. (4认同)
  • 没错,您的解决方案更优化了一些。您甚至可以使用 `exists()` 函数代替 `count()` 以获得最佳优化。 (3认同)