通过枢轴表ID而不是模型ID同步

发布于 2025-02-13 11:41:23 字数 2941 浏览 0 评论 0原文

我想在我的方案顺序中通过枢轴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
        }
    ]
}
idofder_id product_idproduct_id颜色数量
11 11 111
111 1 1黑色10
312黑色1

在更新订单产品时

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

,我想要我的桌子看起来像

idofder_idproduct_id products_id products_id products_id颜色数量
111蓝色12
312蓝色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))"

OrderController

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

order_product迁移

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

有任何解决我的问题的想法吗?

I want to update order products by pivot id with sync method cause in my scenario order can have more than a product of the same id and I want to update products I called their pivot id and delete others that I didn't update, but u know from sync syntax that it accepts ids of products.

Example

That's how my body and pivot table look like when attaching products to order

{
    "products": [
        {
            "product_id": 1,
            "color": "red",
            "quantity": 2
        },
        {
            "product_id": 1,
            "color": "black",
            "quantity": 10
        },
        {
            "product_id": 2,
            "color": "black",
            "quantity": 1
        }
    ]
}
idorder_idproduct_idcolorquantity
111red2
211black10
312black1

When updating the order products

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

how I want my table look like

idorder_idproduct_idcolorquantity
111blue12
312blue5

but got this expected error

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

OrderController

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

order_product migration

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

Any ideas to solve my issue?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

缺⑴份安定 2025-02-20 11:41:23

您需要处理此操作,而无需属于许多关系,并且必须创建一个中间或枢轴模型。

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

那么我希望这对您有帮助,并且可能需要您使用交易预防错误,并添加相应的验证

You need to handle this without belongs to many relation, and you must have to create an intermediate or pivot model.

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

And need to change the order and product model (product model optional if you dont use)

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

In your controller update method

// Assuming that your request structure is

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

You need to create your own sync method

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

I hope this helps you, and probably you need to use a transaction for preventing errors, and, add the respective validations

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文