Heim  >  Fragen und Antworten  >  Hauptteil

Synchronisierung nach PivotTable-ID statt nach Modell-ID

Ich möchte Bestellprodukte anhand der Pivot-ID mithilfe der Synchronisierungsmethode aktualisieren, da in meinem Szenario eine Bestellung mehrere Produkte mit derselben ID enthalten kann und ich das Produkt, dessen Pivot-ID ich aufrufe, aktualisieren und die anderen löschen möchte, die ich nicht aktualisiert habe Produkt, aber Sie wissen aus der Synchronisierungssyntax, dass es die ID des Produkts akzeptiert.

Beispiel

So sehen mein Körper und meine Pivot-Tabelle aus, wenn ich Produkte an eine Bestellung anhänge

{
    "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 Produkt-ID Farbe Menge
1 1 1 Rot 2
2 1 1 Schwarz 10
3 1 2 Schwarz 1

Beim Aktualisieren von Bestellprodukten

{
"products": [
    {
        "id" : 1,
        "product_id" :1 ,
        "color": "blue",
        "quantity": 12
    },
    
    {
        "id" : 3,
        "product_id" :2,
        "color": "blue",
        "quantity": 5
    }
]}

Wie mein Tisch aussehen soll

id order_id Produkt-ID Farbe Menge
1 1 1 Blau 12
3 1 2 Blau 5

Aber dieser erwartete Fehler ist aufgetreten

"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))"

Auftragskontrolleur

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,
    ]);
}

Produktmigration bestellen

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();
    });

Irgendwelche Ideen, wie ich mein Problem lösen kann?

P粉121447292P粉121447292268 Tage vor445

Antworte allen(1)Ich werde antworten

  • P粉207483087

    P粉2074830872024-02-18 12:10:04

    您需要在不属于多个关系的情况下处理此问题,并且必须创建一个中间或枢轴模型。

    class OrderProduct extends Model {
        // optional belongs to order and product method
        protected $fillable = [
            'product_id',
            'order_id',
            'color',
            'quantity'
        ];
    }

    并且需要更改订单和产品型号(如果不用则产品型号可选)

    class Order extends Model {
        public function order_products()
        {
            return $this->hasMany(OrderProduct::class);
        }
    }

    在你的控制器更新方法中

    // 假设你的请求结构是

    [
        '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
            ]
        ]
    ]

    您需要创建自己的同步方法

    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,
        ]);
    }

    我希望这对您有帮助,并且您可能需要使用事务来防止错误,并且添加相应的验证

    Antwort
    0
  • StornierenAntwort