Laravel保存/更新多对多关系


85

谁能帮助我保存多对多关系?我有任务,用户可以有许多任务,任务可以有许多用户(很多),我要实现的是在更新表单中admin可以将多个用户分配给特定任务。这是通过html多重选择输入来完成的

name="taskParticipants[]"

这里要注意的是,通过相同的表单(输入),您可以添加/删除用户,这就是为什么我必须使用sync()的原因。也许我应该从头开始,但不知道从哪里开始...

这是我的用户模型:

public function tasks()
{
    return $this->belongsToMany('Task','user_tasks');
}

任务模型

public function taskParticipants()
{
    return $this->belongsToMany('User','user_tasks');
}

TaskController

public function update($task_id)
{
    if (Input::has('taskParticipants'))
    {
        foreach(Input::get('taskParticipants') as $worker)
        {
            $task2 = $task->taskParticipants->toArray();
            $task2 = array_add($task2,$task_id,$worker);
            $task->taskParticipants()->sync(array($task2));
        }
    }
}

这是表 任务id | title | deadline的结构

user_tasks
id|task_id|user_id

我已经更新了我的代码。 链接
SuperManSL 2014年

4
$workers = Input::get('taskParticipants'); $task->taskParticipants()->sync($workers);这就是您所需要的,只要您从该表单传递给所有分配给任务的用户即可。
Jarek Tkaczyk 2014年

@JarekTkaczyk谢谢,这太神奇了。
Ryu_hayabusa 2015年

Answers:


190

tldr; sync与第二个参数一起使用false


belongsToMany两种模型都具有多对多关系:

// Task model
public function users()
{
  return $this->belongsToMany('User', 'user_tasks'); // assuming user_id and task_id as fk
}

// User model
public function tasks()
{
  return $this->belongsToMany('Task', 'user_tasks');
}

为了添加新的关系,请使用attachsync

两者的区别是:

1 attach将在数据透视表上添加新行,而不检查它是否已经存在。当您具有链接到该关系的其他数据时,这很好,例如:

UserExam与数据透视表链接attempts: id, user_id, exam_id, score

我想这不是您所需要的情况:

$user->tasks()->getRelatedIds(); // [1,2,3,4,5,6]

$user->tasks()->attach([5,6,7]);
// then
$user->tasks()->getRelatedIds(); // [1,2,3,4,5,6,5,6,7]

2 sync,另一方面,要么删除所有关系,并设置它们重新:

$user->tasks()->getRelatedIds(); // [1,2,3,4,5,6]

$user->tasks()->sync([1,2,3]);
// then
$user->tasks()->getRelatedIds(); // [1,2,3]

否则它将建立新的关系而不分离先前的AND而不添加重复项:

$user->tasks()->sync([5,6,7,8], false); // 2nd param = detach
// then
$user->tasks()->getRelatedIds(); // [1,2,3,4,5,6,7,8]

8
如果将其记录在主要文档中而不是API文档中,那就太好了!继续前进。+1。
ceejayoz 2014年

我真的很喜欢带有sync和2nd参数的第二个解决方案。就像我在下面的评论中说的那样,我不能不使用detach。故事是管理员可以将任务分配给用户。他从下拉菜单(多个)中选择用户,字段为参与者[]。所以...:步骤1:管理员将任务A分配给三个用户(您的方法有效,数据库中有3个记录)步骤2:管理员更新了任务A并添加了两个用户(您的方法有效,我们在DB中有5个记录)步骤3:管理员更新任务A并删除1个用户(您的方法失败,我们仍然有5个用户而不是4个用户) 我的更新方法我的代码
SuperManSL 2014年

1
您可以简化关系查询,使其仅$this->belongsToMany('User')使用按字母顺序和单数形式命名表(这样即可task_user代替user_tasks
Kousha 2014年

@Rok如果您始终传递所有相关用户的数组,则可以sync分离使用,不用担心。我建议您在传递单个id相关模型时,只要想“为用户添加新任务”或“将用户分配给任务”,就将第二参数设置为false 。
Jarek Tkaczyk 2014年

1
@FabioAntunessync返回带有的数组detachedattachedupdated列出。attach不会返回任何内容,但是在两种情况下,如果db调用中发生意外情况,您都将获得异常。
Jarek Tkaczyk

105

这是我关于如何保存和更新所有口才关系的说明。

一对一

你必须使用HasOne上的第一款车型,并属于关联的第二种模式

要在第一个模型(HasOne)上添加记录,请使用保存 功能

例:    $post->comments()->save($comment);

要在第二个模型(BelongsTo)上添加记录,请使用 关联函数

例:    $user->account()->associate($account);    $user->save();


一对多

你必须使用的hasMany上的第一款车型,并属于关联在第二模型

要在第一个表(HasMany)上添加记录,请使用save 或saveMany函数

例:    $post->comments()->saveMany($comments);

要在第二个模型(BelongsTo)上添加记录,请使用 关联函数

例:    $user->account()->associate($account);    $user->save();


多对多中

您必须在第一个模型上使用BelongsToMany,在第二个模型上使用 BelongsToMany

要在数据透视表上添加记录,请使用附加同步功能

  • 这两个函数都接受单个ID或ID的数组 

  • 区别在于附加检查同步时记录是否已在数据透视表上存在

例: $user->roles()->attach($roleId);


多态一对多中

您必须在主要模型上使用MorphMany, 在所有(***可用)模型上使用 MorphTo

要在所有其他模型上添加记录,请使用 保存

例:    $course->tags()->save($tag);

数据透视表应包含以下列:

。主要型号

。(***可)ID

。(***可)类型


多态多对多中

您必须在主要模型上使用MorphBy​​Many,并 在所有(***可用)模型上使用 MorphToMany

要在所有其他模型上添加记录,请使用savesaveMany

例:    $course->tags()->save($tag);

例:    $course->tags()->saveMany([$tag_1, $tag_2, $tag_3]);

数据透视表应包含以下列:

。主要型号

。(***可)ID

。(***可)类型


在“具有很多通过”(快捷方式)中:

您必须在第一个表上使用HasManyThrough并在其他两个表上具有正常关系

这对于ManyToMany关系(有数据透视表)不起作用

但是,有一个很好且简单的解决方案。


这是我受此答案启发而写的文章。要检查它很重要:https : //hackernoon.com/eloquent-relationships-cheat-sheet-5155498c209


当他们的正确答案已经超过40个喜欢时,我实际上给出了这个答案,但是是的,我知道这对我有用,很高兴您喜欢:)
Mahmoud Zalt 2016年

1
我希望您知道自己是救世主
Chay22 '16

1
这是一个很好的答案。
caro

1
如何更新一个可能的关系。你解释了如何添加。你能解释一下更新吗?有没有办法像updateMany这样更新记录?谢谢
Hamidreza

3

syncWithoutDetaching([$id_one, $id_two, $id_three]);是您要寻找的。实际上,它确实做了[sync使用第二个参数false]所做的事情!


0

sync函数消除了现有的关系,并使您的数组成为关系的整个列表。您想attach添加关系而不移除其他关系。


我无法使用Attach,因为我在update方法中使用了此代码。故事是,管理员可以更新任务并使用将要参与任务的用户来填写输入参与者[]。因此,我需要检查它是否存在并删除(或不添加新记录)它,或者如果不存在则添加它。
SuperManSL 2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.