首頁  >  問答  >  主體

透過資料透視表 ID 而不是模型 ID 進行同步

我想使用同步方法透過資料透視ID 更新訂單產品,因為在我的場景中訂單可以有多個具有相同ID 的產品,並且我想更新我調用其資料透視ID 的產品並刪除其他我未更新的產品,但你從同步語法知道它接受產品的id。

範例

這就是將產品附加到訂單時我的正文和資料透視表的樣子

{
    "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 顏色 數量
1 1 1 紅色 2
2 1 1 黑色 10
3 1 2 黑色 1

更新訂單產品時

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

我希望我的桌子是什麼樣子

id order_id 產品ID 顏色 數量
1 1 1 藍色 12
3 1 2 藍色 5

但是得到了這個預期的錯誤

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

訂單控制器

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

訂單產品移轉

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

有什麼想法可以解決我的問題嗎?

P粉121447292P粉121447292268 天前446

全部回覆(1)我來回復

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

    我希望這對您有幫助,並且您可能需要使用事務來防止錯誤,並且添加相應的驗證

    回覆
    0
  • 取消回覆