Обновление отношений «один ко многим» с помощью методов updateOrCreate

Моя основная модель Tag имеет отношение «один ко многим» с Product, где одному Tag может быть назначено много Products через отношение tag_id в БД.

В моем представлении редактирования я разрешаю пользователям редактировать тег products. Эти товары можно добавлять/редактировать/удалять в форме запроса.

Каждое поле product в форме берется из массива request(). Например: request('title'),request('price').

Например, я установил $title[$key] как массив request('title').

Мои мысли заключались в том, чтобы перебрать каждый из products для этого tag и updateOrCreate на основе данных запроса. Проблема здесь в том, что нет способа определить, действительно ли этот конкретный product нуждался в обновлении.

TagController — обновление модели продукта (один ко многим)

foreach($tag->products as $key => $product){

  Product::updateOrCreate([
   'id'  => $product->id,
   ],
     [
       'title' => $title[$key],
       'price' => $price[$key],
       'detail' => $detail[$key],
       'order' => $order[$key],
       'tagX' => $tagX[$key],
       'tagY' => $tagY[$key],
       'thumb' => $img[$key],
   ]);
}

Для первоначального обновления tag я установил оператор if, который отлично работает (хотя и беспорядочно) для основного тега img.

TagController — обновление модели тегов

//Update the tag collection
if ($request->hasFile('img')) {
  $tag->update([
    'name' => $name,
    'hashtag' => $hashtag,
    'img' => $imgPub,
  ]);
} else{
  $tag->update([
    'name' => $name,
    'hashtag' => $hashtag,
  ]);
}

Есть ли лучший способ определить, были ли обновлены поля product в запросе?

В идеале я хотел бы, чтобы пользователь мог добавлять/удалять или редактировать products из запроса на редактирование tag, но не удалять существующие изображения продукта, если они не были обновлены. Спасибо!

Рассматривали ли вы возможность добавления флага (столбца) в объект продукта. Таким образом, этот флаг устанавливается после обновления продукта и инициализируется обратно, когда вы выполняете нужное действие, когда продукт был обновлен?

elkolotfi 13.03.2019 09:32
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
5
1
2 061
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Обычно я делаю что-то подобное на стороне интерфейса

<div class = "product">
   <!-- For Products that may be edited -->
   <input type = "hidden" name = "id" value = {{$product->id??0}}>
   <input type = "hidden" name = "action" value = "update">
   <input type = "text" name = "title" value = {{$product->title}}>
      ...
</div>
<div class = "product">
   <!-- For New Products -->
   <input type = "hidden" name = "id" value=0>
   <input type = "hidden" name = "action" value = "add">
   <input type = "text" name = "title" value = "New Title">
      ...
</div>
<div class = "product">
   <!-- For Deleted Products -->
   <input type = "hidden" name = "id" value = {{$product->id}}>
   <input type = "hidden" name = "action" value = "delete">
   <input type = "text" name = "title" value = "New Title">
      ...
</div>

Создайте полезную нагрузку json (массив объектов продукта) с помощью javascript и отправьте запрос ajax на серверную часть.

[{'id':101,'title':'product 1','action':'update'},
{'id':102,'title':'product 2','action':'update'},
... , 
{'id':201,'action':'delete'}, 
{'id':202, 'action':'delete'},
... ,
{'id':0,'title':'new product 1','action':'add'}, 
{'id':0,'title':'new product 2','action':'add'}]

Теперь на стороне сервера прокрутите список продуктов и проверьте действие. В зависимости от действия, сделайте необходимый шаг.

Ответ принят как подходящий

На мой взгляд, вы на ложном пути. Отношение тегов должно быть Многие ко многим.

Вы должны проверить метод sync() Laravel в отношениях ManyToMany. Пожалуйста, проверьте это: https://laravel.com/docs/5.8/eloquent-relationships#many-to-many

Примечания: Добавьте коды в соответствии с вашей бизнес-логикой.

Продукт.php

  public function products(){
    return $this->belongsToMany( 'App\Product', 'product_tags', 'tag_id', 'product_id');
  }

Тег.php

   public function tags(){
     return $this->belongsToMany( 'App\Tag', 'product_tags', 'product_id', 'tag_id');
  }

ПродуктКонтроллер.php

  public function update(Product $products,  Request $request){
    //update the product
    $products->update($request->all());

    //attach new tags to the product 
    $products->tags()->sync($request->input('tag_list'));

    return redirect('articles');
 }

Я не уверен, что это правильный подход. Одному products может быть назначено несколько tag, но products не может быть назначено более чем одному tag.

scopeak 13.03.2019 18:26

Я решил пойти с many to many, как предложил @mayank-dudakiya. Я использовал detach, а затем ->sync() для назначения сводной таблице. Я позволю пользователям обновлять products из отдельного представления, чтобы все было чище.

scopeak 14.03.2019 20:28

@scopeak Просто упомянем, что Eloquent предоставляет функцию syncWithoutDetach(), если вы хотите только прикрепить новые продукты, но не удалять существующие!

Apród Illés 15.03.2019 23:03

Другие вопросы по теме

Похожие вопросы

Атрибуты запроса возвращают null в конструкции
PHP Сортировать три альфа-символа в пользовательском порядке
Разбиение на страницы PHP отлично работает в локальной версии, но не работает на сервере
Как добавить все значение в столбец в базе данных и получить его среднее значение, а затем подсчитать количество строк
Почему Laravel не возвращает записи отношений конкретного пользователя (он возвращает записи всех пользователей)?
Как отображать сегодня и вчера, используя дату?
Попытка вставить данные в пользовательскую таблицу с помощью php
У меня есть 10 файлов Php. когда я включаю один за другим, каждый из них работает правильно, но когда я пишу их в условии «если», какая-то часть этого не работает
Запретить сайту запускать код javascript из базы данных
Php artisan make:model --resource дает функцию параметра модели в контроллере. как их использовать?