#php #laravel #eloquent
#php #laravel #красноречивый
Вопрос:
Моя основная модель 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
запроса на редактирование, но не удалять существующие изображения продукта, если они не были обновлены. Спасибо!
Комментарии:
1. Рассматривали ли вы возможность добавления флага (столбца) к объекту product. Итак, этот флаг устанавливается после обновления продукта и инициализируется обратно, как только вы выполняете нужное действие, когда продукт был обновлен?
Ответ №1:
На мой взгляд, вы на неверном пути. Отношения тегов должны быть многие ко многим.
Вы должны проверить sync()
метод Laravel в отношениях ManyToMany. Пожалуйста, проверьте это: https://laravel.com/docs/5.8/eloquent-relationships#many-to-many
Примечания: Пожалуйста, добавляйте коды в соответствии с вашей бизнес-логикой.
Product.php
public function products(){
return $this->belongsToMany( 'AppProduct', 'product_tags', 'tag_id', 'product_id');
}
Tag.php
public function tags(){
return $this->belongsToMany( 'AppTag', 'product_tags', 'product_id', 'tag_id');
}
ProductController.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');
}
Комментарии:
1. Я не уверен, что это правильный подход. Одному может быть несколько,
products
назначенных одному,tag
ноproducts
не может быть назначено более одногоtag
.2. Я решил использовать
many to many
то, что предложил @mayank-dudakiya . Я использовалdetach
then->sync()
для присвоения сводной таблице. Я позволю пользователям обновлятьproducts
из отдельного представления, чтобы все было чище.3. @scopeak Просто для упоминания eloquent предоставляет функцию syncWithoutDetach(), если вы хотите только присоединять новые продукты, но не удалять существующие!
Ответ №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'}]
Теперь на стороне серверной части просмотрите список продуктов и проверьте наличие действий. В зависимости от действия, выполните необходимый шаг.