Czy ktoś może mi pomóc, jak uratować związek wielu za wielu? Mam zadania, użytkownik może mieć wiele zadań, a zadanie może mieć wielu użytkowników (od wielu do wielu). Chcę tylko, aby w formularzu aktualizacji administrator mógł przypisać wielu użytkowników do określonego zadania. Odbywa się to za pomocą wielokrotnego wyboru html
name="taskParticipants[]"
Problem polega na tym, że za pomocą tego samego formularza (danych wejściowych) można dodawać / usuwać użytkowników, dlatego muszę używać sync (). Może powinienem zacząć od początku, ale nie wiem od czego zacząć ...
To jest mój model użytkownika:
public function tasks()
{
return $this->belongsToMany('Task','user_tasks');
}
Model zadań
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));
}
}
}
To jest struktura tabel id | tytuł | termin realizacji zadań
user_tasks
id|task_id|user_id
laravel
laravel-4
eloquent
relationship
SuperManSL
źródło
źródło
$workers = Input::get('taskParticipants'); $task->taskParticipants()->sync($workers);
i to wszystko, czego potrzebujesz, o ile przekażesz z tego formularza wszystkich użytkowników przydzielonych do zadania.Odpowiedzi:
tldr; Używaj
sync
z drugim parametremfalse
Relacja wiele do wielu występuje
belongsToMany
w obu modelach:// 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'); }
Aby dodać nową relację, użyj
attach
lubsync
.Różnica między nimi to:
1
attach
doda nowy wiersz do tabeli przestawnej bez sprawdzania, czy już tam jest. Dobrze, gdy masz dodatkowe dane powiązane z tą relacją, na przykład:User
iExam
połączone z tabelą przestawnąattempts: id, user_id, exam_id, score
Przypuszczam, że nie tego potrzebujesz w swojej sytuacji:
$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
z drugiej strony usunie wszystkie relacje i utworzy je od nowa:$user->tasks()->getRelatedIds(); // [1,2,3,4,5,6] $user->tasks()->sync([1,2,3]); // then $user->tasks()->getRelatedIds(); // [1,2,3]
lub utworzy nowe relacje bez odłączania poprzedniego AND bez dodawania duplikatów:
$user->tasks()->sync([5,6,7,8], false); // 2nd param = detach // then $user->tasks()->getRelatedIds(); // [1,2,3,4,5,6,7,8]
źródło
$this->belongsToMany('User')
jeśli użyjesz nazwy tabeli alfabetycznie i liczby pojedynczej (task_user
a więc zamiastuser_tasks
)sync
z odłączaniem, bez obaw. Sugeruję użycie drugiego parametru ustawionego na false, gdy chcesz „dodać nowe zadanie dla użytkownika” lub „przypisać użytkownika do zadania”, gdy przekazujesz jedenid
z powiązanego modelu.sync
zwraca tablicędetached
,attached
iupdated
list.attach
nic nie zwraca, ale w obu przypadkach wystąpiłby wyjątek, gdyby coś nieoczekiwanego wydarzyło się w wywołaniach bazy danych.Oto moje notatki o tym, jak zapisywać i aktualizować wszystkie elokwentne relacje.
w jeden do jednego :
Musisz użyć HasOne na pierwszym modelu i BelongsTo na drugim modelu
aby dodać rekord na pierwszym modelu ( HasOne ) użyj funkcji zapisu
przykład:
$post->comments()->save($comment);
aby dodać rekord w drugim modelu ( BelongsTo ), użyj funkcji skojarzonej
przykład:
$user->account()->associate($account); $user->save();
w jeden do wielu :
Musisz użyć HasMany na pierwszym modelu i BelongsTo na drugim modelu
aby dodać na pierwszej tabeli ( hasMany ) użyć Zapisz lub saveMany funkcje
przykład:
$post->comments()->saveMany($comments);
aby dodać rekord w drugim modelu ( BelongsTo ), użyj funkcji skojarzonej
przykład:
$user->account()->associate($account); $user->save();
w Wiele do wielu :
Musisz użyć BelongsToMany w pierwszym modelu i BelongsToMany w drugim modelu
aby dodać rekordy do tabeli przestawnej, użyj funkcji dołączania lub synchronizacji
obie funkcje akceptują pojedynczy identyfikator lub tablicę identyfikatorów
różnica polega na tym, że dołączanie sprawdza, czy rekord już istnieje w tabeli przestawnej, a synchronizacja nie
przykład:
$user->roles()->attach($roleId);
w Polimorficznym jeden do wielu :
Musisz użyć MorphMany na głównym modelu i MorphTo na wszystkich (*** w stanie) modelach
aby dodać rekordy we wszystkich innych modelach, użyj opcji save
przykład:
$course->tags()->save($tag);
tabela przestawna powinna mieć następujące kolumny:
. główny identyfikator modelu
. (*** w stanie) ID
. (*** w stanie) Wpisz
w Polimorficznym Wiele do wielu :
Musisz użyć MorphByMany na głównym modelu i MorphToMany na wszystkich (*** w stanie) modelach
aby dodać rekordy we wszystkich innych modelach, użyj opcji save lub saveMany
przykład:
$course->tags()->save($tag);
przykład:
$course->tags()->saveMany([$tag_1, $tag_2, $tag_3]);
tabela przestawna powinna mieć następujące kolumny:
. główny identyfikator modelu
. (*** w stanie) ID
. (*** w stanie) Wpisz
w Ma wiele do przejścia (skrót):
Musisz użyć HasManyThrough na pierwszej tabeli i mieć normalne relacje na pozostałych 2 tabelach
to nie działa w przypadku relacji ManyToMany (gdzie jest tabela przestawna)
jednak jest na to ładne i łatwe rozwiązanie.
Oto artykuł, który napisałem, zainspirowany tą odpowiedzią. Ważne, aby to sprawdzić: https://hackernoon.com/eloquent-relationships-cheat-sheet-5155498c209
źródło
updateMany
coś takiego? dziękisyncWithoutDetaching([$id_one, $id_two, $id_three]);
jest tym, czego szukasz. Właściwie robi dokładnie to samo [sync
z drugim parametremfalse
]!źródło
sync
Funkcja likwidujący relacje wychodzące i czyni swoją tablicę całą listę stosunków. Zamiastattach
tego chcesz dodać relacje bez usuwania innych.źródło