Почему синхронизация дублирует синхронизацию в сводной таблице, если я выбираю больше, чем изображение?
В моем приложении при добавлении нового конкурса пользователь может выбрать одно или несколько изображений/документов, и путь к файлу будет сохранен в таблице файлов и синхронизирован с данными в сводной таблице competition_file
.
Вот интерфейс создания
Вот функция магазина на моем контроллере
public function store($competition, Request $request, Team $team)
{
if ($request->has('photos') && is_array($request->photos)) {
$files = $this->filesRepo->getByUuids($request->photos);
$fileId = $files->pluck('id')->toArray();
if ($files->isNotEmpty()) {
$forSync = array_fill_keys($fileId, ['competition_id' => $competition,'team_id' => $request->team,'type' => $request->type,'share_type' => $request->share_type]);
$team->documents()->sync($forSync);
}
}
return redirect(route('documents.index',$competition))->with('success', 'Document updated.');
}
Вот коды отношений в моей модели
public function documents()
{
return $this->belongsToMany(File::class,'competition_file','team_id','file_id')->wherePivot('type', 'document');
}
Когда я выбираю более одного изображения, как показано ниже, оно создает дубликат в таблице competition_file
.
Вот как это сохраняется в сводной таблице competition_file
с повторяющимися данными
Но если сбросить данные до sync
, когда я выбрал два изображения, он показывает только два массива, см. Коды ниже.
public function store($competition, Request $request, Team $team)
{
if ($request->has('photos') && is_array($request->photos)) {
$files = $this->filesRepo->getByUuids($request->photos);
$fileId = $files->pluck('id')->toArray();
if ($files->isNotEmpty()) {
$forSync = array_fill_keys($fileId, ['competition_id' => $competition,'team_id' => $request->team,'type' => $request->type,'share_type' => $request->share_type]);
dd($forSync);
$team->documents()->sync($forSync);
}
}
return redirect(route('documents.index',$competition))->with('success', 'Document updated.');
}
Результат
И если я удалю Dump
и перезагружу ту же страницу, она синхронизируется правильно
А если я повторю попытку без Dump
, и если я выберу два изображения и сохраню их, создастся дубликат?
Мне нужно знать, что может создавать дублирующую синхронизацию.
Я надеюсь, что мой вопрос ясен, может кто-нибудь, пожалуйста, помогите мне.
Вам не нужно 'team_id' => $request->team
в array_fill_keys, так как синхронизация происходит через отношение documents
к командному объекту — team_id должен заполняться автоматически
@Donkarnash, почему идентификатор команды заполняется автоматически? при этом пользователю нужно выбрать команду при добавлении файлов
@Donkarnash пользователь может выбрать команду 1 или команду 2 при добавлении файла, поэтому я использовал 'team_id' => $request->team
@Donkarnash, но если я удалю $forSync = array_fill_keys($fileId, ['competition_id' => $competition,'type' => $request->type,'share_type' => $request->share_type]);
и отправлю team_id
, будет синхронизировано значение null, в чем может быть проблема?
Но тогда что такое параметр $team во внедрении метода? Когда вы синхронизируете связанную запись, идентификатор экземпляра модели, который вызывает отношение, заполняется автоматически, что является преимуществом, кроме того, что он удаляет записи для идентификаторов, которые отсутствуют в синхронизации.
team_id will be synced null ?
Нет, он автоматически заполнит team_id $team->id. Если вам нужно, чтобы team_id соответствовал указанному в $request, вы можете сделать Team::findOrFail($request->team)->documents()->sync([...])
@Donkarnash, когда я dd($team->id);
показывает ноль?
Тогда вам стоит попробовать $forSync = array_fill_keys($fileId, ['competition_id' => $competition,'type' => $request->type,'share_type' => $request->share_type]);
и Team::findOrFail($request->team)->documents()->sync($forSync);
Только на пользу последующим посетителям.
public function store($competition, Request $request, Team $team)
{
if ($request->has('photos') && is_array($request->photos)) {
$files = $this->filesRepo->getByUuids($request->photos);
$fileId = $files->pluck('id')->toArray();
if ($files->isNotEmpty()) {
$forSync = array_fill_keys($fileId, [
'competition_id' => $competition,
'type' => $request->type,
'share_type' => $request->share_type
]);
//If the implicit route model binding is not working
//if $team is null or you need to explicitly set the team
//selected by user and which is not passed as route param
Team::findOrFail($request->team)->documents()->sync($forSync);
}
}
return redirect(route('documents.index',$competition))
->with('success', 'Document updated.');
}
Установите уникальное ограничение на уровне БД (например,
['competition_id', 'team_id', 'file_id'] as unique_competition_team_file
), затем продолжите работу. Вам нужно будет изменить проверку запроса, проверив, существует ли уже тот же файл (возможно, с пользовательским классом правил), но вы защитите свою БД от ненужных данных, что (должно быть) конечной целью.