Maison > Questions et réponses > le corps du texte
Je souhaite mettre à jour les produits de la commande par ID pivot en utilisant la méthode de synchronisation car dans mon scénario, une commande peut avoir plusieurs produits avec le même ID et je souhaite mettre à jour le produit dont j'appelle l'ID pivot et supprimer les autres que je n'ai pas mis à jour. produit, mais vous savez grâce à la syntaxe de synchronisation qu'il accepte l'identifiant du produit.
Exemple
Voici à quoi ressemblent mon corps et mon tableau croisé dynamique lorsque je joins des produits à une commande
{ "products": [ { "product_id": 1, "color": "red", "quantity": 2 }, { "product_id": 1, "color": "black", "quantity": 10 }, { "product_id": 2, "color": "black", "quantity": 1 } ] }
id | order_id | ID produit | Couleur | Quantité |
---|---|---|---|---|
1 | 1 | 1 | Rouge | 2 |
2 | 1 | 1 | Noir | 10 |
3 | 1 | 2 | Noir | 1 |
Lors de la mise à jour des produits commandés
{ "products": [ { "id" : 1, "product_id" :1 , "color": "blue", "quantity": 12 }, { "id" : 3, "product_id" :2, "color": "blue", "quantity": 5 } ]}
À quoi je veux que ma table ressemble
id | order_id | ID produit | Couleur | Quantité |
---|---|---|---|---|
1 | 1 | 1 | Bleu | 12 |
3 | 1 | 2 | Bleu | 5 |
Mais j'ai eu cette erreur attendue
"message": "SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '1' for key 'PRIMARY' (SQL: insert into `order_product` (`color`, `created_at`, `id`, `order_id`, `product_id`, `quantity`, `size`, `updated_at`) values (blue, 2022-07-04 21:38:25, 7, 3, 1, 12, S, 2022-07-04 21:38:25))"
Contrôleur de commandes
public function update(AdminUpdateOrderRequest $request, $id) { $orderValidated = $request->validated(); $order = Order::findOrFail($id); $order->update($orderValidated); if (isset($orderValidated['products'])) { $order->products()->sync($orderValidated['products']); } DB::table return OrderResource::make($order)->additional([ 'success' => true, ]); }
Commander la migration du produit
Schema::create('order_product', function (Blueprint $table) { $table->id(); $table->foreignId('order_id')->nullable()->constrained('orders')->onUpdate('cascade'); $table->foreignId('product_id')->nullable()->constrained('products')->onUpdate('cascade'); $table->integer('quantity')->nullable(); $table->string('color')->nullable(); $table->timestamps(); });
Des idées pour résoudre mon problème ?
P粉2074830872024-02-18 12:10:04
Vous devez gérer cela sans appartenir à plusieurs relations et créer un modèle intermédiaire ou pivot.
class OrderProduct extends Model { // optional belongs to order and product method protected $fillable = [ 'product_id', 'order_id', 'color', 'quantity' ]; }
Et vous devez modifier la commande et le modèle de produit (s'il n'est pas utilisé, le modèle de produit est facultatif)
class Order extends Model { public function order_products() { return $this->hasMany(OrderProduct::class); } }
Dans la méthode de mise à jour de votre contrôleur
// Supposons que la structure de votre demande est
[ 'id' => 1, // Order id, 'order_attribute_1', // Any of your order model attribute 'order_attribute_2', // Any of your order model attributes 'products' => [ [ 'id' => null, // id of the order_product table so, null cause is a new added product 'order_id' => 1, // id of order 'product_id' => 1// id of product 'color' => 'blue', 'quantity' => 12 ], [ 'id' => 1, // id of the order_product table so, has id cause are you updating an existent product in the order 'order_id' => 1, // id of order 'product_id' => 1// id of product 'color' => 'blue', 'quantity' => 5 ] ] ]
Vous devez créer votre propre méthode de synchronisation
public function update(AdminUpdateOrderRequest $request, $id) { $orderValidated = $request->validated(); $order = Order::findOrFail($id); $order->update($orderValidated); // start simulation of sync method $new_order_products = []; // id of order_product to preserve $order_products_to_keep = []; // I hope you have the corresponding products validation on your request class foreach ($request['products'] as $request_product) { // need to create new product in order if (empty($request_product['id'])) { $new_order_products[] = [ 'product_id' => $request_product['product_id'], 'order_id' => $request_product['order_id'], 'color' => $request_product['color'], 'quantity' => $request_product['quantity'] ] } else { // find the order_order product register $order_product = OrderProduct::find(request_product['id']); // update all except the order id $order_product->update([ 'product_id' => $request_product['product_id'], 'color' => $request_product['color'], 'quantity' => $request_product['quantity'] ]); // as exists this order_product will be preserved $order_products_to_keep[] = $order_product->id; } } // calculate the order_products to delete (if not present means that needs to be deleted) foreach ($order->order_products as $order_product) { if (!in_array($order_products_to_keep, $order_product->id)) { $order_product->delete(); } } // mass insertion of new order_products $order->order_products()->createMany($new_order_products); DB::table return OrderResource::make($order)->additional([ 'success' => true, ]); }
J'espère que cela vous aidera et vous souhaiterez peut-être utiliser des transactions pour éviter les erreurs et ajouter une validation en conséquence