【问题标题】:Laravel relationships attach if not already attached如果尚未附加 Laravel 关系,则附加
【发布时间】:2018-01-03 12:38:18
【问题描述】:

如果尚未附加关系,是否有一种快速附加关系的方法。我正在使用此代码来更新模型的关系;

        if (!empty($request->get('roles')) && is_array($request->get('roles'))) {
            $message->Roles()->attach($request->get('roles'));
        }
        if (!empty($request->get('users')) && is_array($request->get('users'))) {
            $message->Users()->attach($request->get('users'));
        }

但是我收到了这个错误,我就是这个错误;

SQLSTATE[23000]:完整性约束违规:1062 键“PRIMARY”的重复条目“1-41”(SQL:插入message_usermessage_iduser_id)值(1、41),( 1, 42), (1, 43), (1, 44), (1, 45), (1, 46), (1, 47), (1, 48), (1, 49), (1, 50))

我想避免通过很长的数组检查列表来检查哪些用户尚未附加并附加它们。如果这是唯一的方法,请告诉我。

我在想类似的东西;

$message->Users()->attachIfNotAttached($request->get('users'));

【问题讨论】:

  • MySQL 支持INSERT IGNORE,但我不认为 laravel 也支持。
  • 我认为唯一的解决方案是在附加之前检查每个用户是否存在关系。
  • $request->get('users') 中存储了什么?用户 ID?
  • $request->get('users') 是一个用户 ID 列表的数组,例如 [41, 42, 43, 44, 45, 46, 47, 48, 49, 50] 来自上面的例子

标签: php mysql laravel laravel-5.4


【解决方案1】:

使用syncWithoutDetachingsync([arr], false) 在代码中看起来更简洁,但执行速度比attach() 慢25 倍。这是因为它检查每个 id 并为每个项目执行单独的数据库插入。

我建议通过扩展 eloquent 或在您的模型类上创建新方法来构建 Paul Spiegel's answer

在我的用例中,我有一个 Feed 类和一个 Post 类,它们由多对多枢轴链接。我在我的 Feed 类中添加了以下方法。

public function attachUniquePosts($ids)
{
    $existing_ids = $this->posts()->whereIn('posts.id', $ids)->pluck('posts.id');
    $this->posts()->attach($ids->diff($existing_ids));
}
  • 使用syncWithoutDetaching() 将 20 个帖子附加到提要平均占用 0.107s
  • 将 20 个帖子附加到提要使用 attachUniquePosts() 平均耗时 0.004 秒

【讨论】:

  • 分离 $ids 中缺失的元素?
【解决方案2】:

Laravel 有内置的方法 - syncWithoutDetaching:

$message->Users()->syncWithoutDetaching($request->get('users'));

【讨论】:

  • 这是更好的答案
  • 更好的答案。该方法应该有一个别名,syncUnique() 或其他东西。 syncWithoutDetaching 的效果并不完全直观。
  • 这与 OP 问题无关,这是同步的,但 OP 想要附加
  • @behz4d 这正是 OP 想要的。它将请求中的所有用户附加到尚未附加的消息中。 “WithoutDetaching”部分确保没有未包含在请求中的用户被分离。
  • Laravel 的同步方法有一个明显的限制,即它们不支持额外的数据透视数据,但 attach 支持。因此,如果您有一个带有额外列的数据透视表,则不使用 syncWithoutDetaching不幸的是一个选择。相反,您必须遵循已接受的答案。
【解决方案3】:

这样的事情可能会奏效:

获取已经附加的ID:

$attachedIds = $message->Users()->whereIn('id', $request->get('users'))->pluck('id');

从请求数组中移除附加的 ID:

$newIds = array_diff($request->get('users'), $attachedIds);

附加新 ID:

$message->Users()->attach($newIds);

【讨论】:

  • 谢谢。这就是我一直在寻找的。​​span>
猜你喜欢
  • 2014-05-13
  • 2022-07-03
  • 1970-01-01
  • 2020-08-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多