라 라벨은 다 대다 관계 저장 / 업데이트


85

누구나 다 대다 관계를 구하는 방법에 대해 나를 도울 수 있습니까? 나는 작업이 있고, 사용자는 많은 작업을 가질 수 있고 작업은 많은 사용자 (다 대다)를 가질 수 있습니다. 내가 달성하고 싶은 것은 업데이트 양식에서 관리자가 특정 작업에 여러 사용자를 할당 할 수 있다는 것입니다. 이것은 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 jul.

4
$workers = Input::get('taskParticipants'); $task->taskParticipants()->sync($workers);작업에 할당 된 모든 사용자를 해당 양식에서 전달하는 한 그게 전부입니다.
Jarek Tkaczyk

@JarekTkaczyk 감사합니다.
Ryu_hayabusa

답변:


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

새로운 관계를 추가하려면 attach또는 sync.

둘의 차이점은 다음과 같습니다.

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]

sync반면에 2 는 모든 관계를 제거하고 새로 설정합니다.

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

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

또는 이전을 분리하지 않고 중복을 추가하지 않고 새로운 관계를 설정합니다.

$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

동기화 및 두 번째 매개 변수가있는 두 번째 솔루션을 정말 좋아합니다. 아래 코멘트에서 말했듯이 분리를 사용하지 않을 여유가 없습니다. 이야기는 관리자가 사용자에게 작업을 할당 할 수 있다는 것입니다. 그는 드롭 다운 (다중)에서 사용자를 선택합니다. 필드는 참가자 []입니다. 그래서 ... : 1 단계 : 관리자가 작업 A를 3 명의 사용자에게 할당합니다 (귀하의 방법이 작동하고, DB에 3 개의 레코드가 있음) 2 단계 : 관리자가 작업 A를 업데이트하고 2 명의 사용자를 추가합니다 (귀하의 방법이 작동 함, 우리는 DB에 5 개의 레코드가 있음). 3 단계 : 관리자가 작업 A를 업데이트하고 1 명의 사용자를 제거합니다 (귀하의 방법이 실패했습니다. 4 명이 아닌 5 명의 사용자가 있습니다) 내 업데이트 방법 내 코드
SuperManSL

1
$this->belongsToMany('User')테이블 이름을 알파벳순과 단수 ( task_user대신 user_tasks) 를 사용하는 경우에만 관계 쿼리를 단순화 할 수 있습니다.
Kousha

@Rok 항상 모든 관련 사용자의 배열을 전달한 다음 sync분리 하여 사용 하면 걱정할 필요가 없습니다. id관련 모델 중 하나를 전달할 때 '사용자를위한 새 작업 추가'또는 '작업에 사용자 할당'을 원할 때마다 false로 설정된 두 번째 매개 변수를 사용하는 것이 좋습니다 .
Jarek Tkaczyk

1
@FabioAntunes은 sync와 배열 반환 detached, attachedupdated목록을. attach아무것도 반환하지 않지만 두 경우 모두 db 호출에서 예기치 않은 일이 발생하면 예외가 발생합니다.
Jarek Tkaczyk 2015

105

모든 Eloquent 관계를 저장하고 업데이트하는 방법에 대한 제 노트입니다.

에서 일대일 :

당신은 사용할 필요가 hasOne의를 첫 번째 모델과에 에 BelongsTo 두 번째 모델

첫 번째 모델 ( HasOne ) 에 레코드를 추가 하려면 저장  기능을 사용하십시오.

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

두 번째 모델 ( NoneTo ) 에 레코드를 추가 하려면 연관 함수를 사용하십시오. 

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


에서 많은 한 가지 :

첫 번째 모델에서는 HasMany 를 사용하고 두 번째 모델 에서는 OwnerTo 를 사용해야 합니다.

첫 번째 테이블 ( HasMany ) 에 레코드를 추가 하려면 save  또는 saveMany 함수를 사용하십시오.

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

두 번째 모델 ( NoneTo ) 에 레코드를 추가 하려면 연관 함수를 사용하십시오. 

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


대다 :

당신은 사용할 필요가  BelongsToMany을 첫 번째 모델에 BelongsToMany 두 번째 모델

피벗 테이블에 레코드를 추가하려면 연결 또는 동기화 기능을 사용 하십시오.

  • 두 함수 모두 단일 ID 또는 ID 배열을 허용합니다. 

  • 차이점은 동기화하지 않는 동안 레코드가 피벗 테이블에 이미 존재하는지 확인하는 것입니다.

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


에서 많은 다형성 하나 :

메인 모델에서는  MorphMany 를, 모든 (*** able) 모델 에서는 MorphTo 를 사용해야  합니다.

다른 모든 모델에 레코드를 추가하려면  save

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

피벗 테이블에는 다음 열이 있어야합니다.

. 주 모델 ID

. (*** able) ID

. (*** able) 유형


에서 다형성 많은 많은 :

메인 모델에서는  MorphByMany 를, 모든 (*** able) 모델 에서는 MorphToMany 를 사용해야  합니다.

다른 모든 모델에 레코드를 추가하려면 save 또는 saveMany

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

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

피벗 테이블에는 다음 열이 있어야합니다.

. 주 모델 ID

. (*** able) ID

. (*** able) 유형


많은 통해 가지고 (바로 가기) :

첫 번째 테이블에서 HasManyThrough 를 사용 하고 다른 두 테이블에서 정상적인 관계를 가져야합니다.

ManyToMany 관계 (피벗 테이블이있는 곳)에서는 작동하지 않습니다.

그러나 그것을위한 좋고 쉬운 해결책이 있습니다.


이 답변에서 영감을 얻은 기사가 있습니다. 확인하는 것이 중요합니다 : https://hackernoon.com/eloquent-relationships-cheat-sheet-5155498c209


사실 그들은 이미 정답에 40 좋아하는 이상했다이 답변을 배치하지만, 그래 난이가 나를 위해 :) 좋아하면 다행 얼마나 유용 알
마흐무드 Zalt을

1
난 당신이 구세주임을 알고 싶은
Chay22

1
이것은 훌륭한 대답입니다.
caro

1
관계를 업데이트하는 방법. u를 추가하는 방법을 설명했습니다. 업데이트에 대해 설명해 주시겠습니까? 이와 같은 레코드를 업데이트하는 방법 updateMany이 있습니까? 감사
Hamidreza

3

syncWithoutDetaching([$id_one, $id_two, $id_three]);당신이 찾고있는 것입니다. 실제로 [ sync2nd param false]이하는 것과 똑같은 일을합니다 !


0

sync함수는 기존 관계를 제거하고 배열을 전체 관계 목록으로 만듭니다. attach대신 다른 관계를 제거하지 않고 관계를 추가 하려고 합니다.


업데이트 메서드 내에서이 코드를 사용하고 있기 때문에 첨부를 사용할 수 없습니다. 이야기는 관리자가 작업을 업데이트하고 입력 참가자 []를 작업에 참여할 사용자로 채울 수 있다는 것입니다. 따라서 존재하는지 확인하고 삭제하거나 새 레코드를 추가하지 않거나 존재하지 않는 경우 추가해야합니다.
SuperManSL
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.