Maison  >  Questions et réponses  >  le corps du texte

Synchroniser par ID de tableau croisé dynamique au lieu de l'ID de modèle

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粉121447292P粉121447292219 Il y a quelques jours400

répondre à tous(1)je répondrai

  • P粉207483087

    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

    répondre
    0
  • Annulerrépondre