Может ли кто-нибудь помочь мне спасти отношения "многие-ко-многим"? У меня есть задачи, у пользователя может быть много задач, а у задачи может быть много пользователей (от многих ко многим). Я хочу добиться того, чтобы в форме обновления администратор мог назначить нескольких пользователей для конкретной задачи. Это делается с помощью ввода множественного выбора 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
laravel
laravel-4
eloquent
relationship
SuperManSL
источник
источник
$workers = Input::get('taskParticipants'); $task->taskParticipants()->sync($workers);
и это все, что вам нужно, если вы перейдете из этой формы всех пользователей, назначенных задаче.Ответы:
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
добавит новую строку в сводную таблицу, не проверяя, есть ли она там. Хорошо, когда у вас есть дополнительные данные, связанные с этим отношением, например:User
иExam
связан со сводной таблицей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]
или он установит новые отношения без отсоединения предыдущего И без добавления дубликатов:
$user->tasks()->sync([5,6,7,8], false); // 2nd param = detach // then $user->tasks()->getRelatedIds(); // [1,2,3,4,5,6,7,8]
источник
$this->belongsToMany('User')
используя имя таблицы в алфавитном порядке и в единственном числе (то естьtask_user
вместоuser_tasks
)sync
с отсоединением, не беспокойтесь. Я предлагаю использовать второй параметр со значением false, когда вы хотите «добавить новую задачу для пользователя» или «назначить пользователя для задачи», когда вы передаете однуid
из связанных моделей.sync
возвращает массивdetached
,attached
иupdated
списки.attach
ничего не возвращает, но в обоих случаях вы получите исключение, если что-то неожиданное случится в вызовах db.Вот мои заметки о том, как сохранять и обновлять все отношения Eloquent.
в один к одному :
Вы должны использовать HasOne на первой модели и BelongsTo на второй модели.
для добавления записи по первой модели ( HasOne ) используйте функцию сохранения
пример:
$post->comments()->save($comment);
чтобы добавить запись во вторую модель ( BelongsTo ), используйте ассоциированную функцию
пример:
$user->account()->associate($account); $user->save();
от одного ко многим :
Вы должны использовать HasMany на первой модели и BelongsTo на второй модели.
чтобы добавить запись на первые таблицы ( HasMany ) использовать сохранить или saveMany функции
пример:
$post->comments()->saveMany($comments);
чтобы добавить запись во вторую модель ( BelongsTo ), используйте ассоциированную функцию
пример:
$user->account()->associate($account); $user->save();
во многих для многих :
Вы должны использовать BelongsToMany на первой модели и BelongsToMany на второй модели.
добавлять записи об использовании сводной таблицы присоединять или синхронизации функции
обе функции принимают один идентификатор или массив идентификаторов
разница в том, что прикрепление проверяет, существует ли уже запись в сводной таблице, а синхронизация - нет.
пример:
$user->roles()->attach($roleId);
в полиморфном от одного ко многим :
Вы должны использовать MorphMany на основной модели и MorphTo на всех (*** способных) моделях.
для добавления записей по всем остальным моделям используйте сохранение
пример:
$course->tags()->save($tag);
сводная таблица должна иметь следующие столбцы:
. ID основной модели
. (*** в состоянии) ID
. (*** в состоянии) Тип
в полиморфном Многие ко многим :
Вы должны использовать MorphByMany на основной модели и MorphToMany на всех (*** способных) моделях
для добавления записей по всем остальным моделям используйте save или saveMany
пример:
$course->tags()->save($tag);
пример:
$course->tags()->saveMany([$tag_1, $tag_2, $tag_3]);
сводная таблица должна иметь следующие столбцы:
. ID основной модели
. (*** в состоянии) ID
. (*** в состоянии) Тип
in Has Many Through (ярлык):
Вы должны использовать HasManyThrough в первой таблице и иметь нормальные отношения в двух других таблицах
это не работает для отношений ManyToMany (где есть сводная таблица)
однако для этого есть хорошее и простое решение.
Вот статья, которую я написал, вдохновленный этим ответом. Важно это проверить: https://hackernoon.com/eloquent-relationships-cheat-sheet-5155498c209
источник
updateMany
? спасибоsyncWithoutDetaching([$id_one, $id_two, $id_three]);
это то, что вы ищете. На самом деле он делает то, что делает [sync
со вторым параметромfalse
]!источник
sync
Функция стирает покидающих отношения и делает ваш массив весь список отношений.attach
Вместо этого вы хотите добавить отношения, не удаляя другие.источник