如果尚未附加 Laravel 关系,则附加

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/45356606/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-14 16:23:18  来源:igfitidea点击:

Laravel relationships attach if not already attached

phpmysqllaravellaravel-5.4

提问by Karim

Is there a quick way of attaching relationships if they're not already attached. I am using this code to update relations of a model;

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

        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'));
        }

But I am getting this error which I am this error;

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

SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '1-41' for key 'PRIMARY' (SQL: insert into message_user(message_id, user_id) values (1, 41), (1, 42), (1, 43), (1, 44), (1, 45), (1, 46), (1, 47), (1, 48), (1, 49), (1, 50))

SQLSTATE[23000]: 完整性约束违规: 1062 Duplicate entry '1-41' for key 'PRIMARY' (SQL: insert into message_user( message_id, user_id) values (1, 41), (1, 42), (1, 43), ( 1, 44), (1, 45), (1, 46), (1, 47), (1, 48), (1, 49), (1, 50))

I want to avoid going through a very long list of array check which users are not already attached and attaching them. Also let me know if this is the only way.

我想避免经过很长的数组检查列表,哪些用户尚未附加并附加它们。也让我知道这是否是唯一的方法。

I am thinking something like;

我在想类似的事情;

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

采纳答案by Paul Spiegel

Something like this might work:

像这样的事情可能会奏效:

Get the IDs that are already attached:

获取已附加的 ID:

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

Remove the attached IDs from the request array:

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

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

Attach the new IDs:

附加新 ID:

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

回答by Karim

Laravel has built-in method for this - syncWithoutDetaching:

Laravel 为此提供了内置方法 - syncWithoutDetaching

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

回答by Kiee

Using syncWithoutDetachingor sync([arr], false)looks cleaner in code, but performs 25x slowerthan attach(). This is because it checks each id and performs individual database inserts per item.

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

I'd suggest building upon Paul Spiegel's answerby extending eloquent or creating a new method on your model class.

我建议通过扩展 eloquent 或在模型类上创建新方法来构建Paul Spiegel 的答案

In my use case I have a Feedclass and a Postclass linked by a many to many pivot. I added the following method to my Feed class.

在我的用例中,我有一个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));
}
  • Attaching 20 posts to a feed using syncWithoutDetaching()took on average 0.107s
  • Attaching 20 posts to a feed using attachUniquePosts()took on average 0.004s
  • 使用将 20 个帖子附加到提要syncWithoutDetaching()平均需要 0.107 秒
  • 使用将 20 个帖子附加到提要 attachUniquePosts()平均需要 0.004 秒