當你有多對多的 tables,需要簡單、輕鬆、快速處理中間 pivot table 資料時
優化了原本維護 pivot table 的複雜程度
建立 orders
products
order_products
三個資料表
建立 Order
Product
OrderProduct
三個 model
建立新訂單時,需要
$data = $request->data;
$items = $data['products'] // [1, 2, 3, ...] product_ids
// 建立訂單
$newOrder = Order::create($data['meta']);
// 建立訂單與商品的關聯
foreach ($items as $item) {
OrderProduct::create(['order_id' => $newOrder->id, 'product_id' => $item]);
}
更新訂單時,需要 (最麻煩部分)
$order = Order::find($id);
$oldProductIds = $order->products->pluck('id'); // [1, 2, 3]
$newProductIds = $request['data']['products']; // [3, 4, 5]
// find and destroy old items needed to be removed
$removeIds = array_filter(function ($item) use ($oldProductIds, $newProductIds) {
return !in_array($newProductIds, $item);
}, $oldProductIds);
OrderProduct::where('order_id', $id)->whereIn('product_id', $removeIds)->delete();
// create new items
foreach ($newProductIds as $item) {
OrderProduct::firstOrCreate(['order_id' => $id, 'product_id' => $item]);
}
建立 orders
products
order_product
三個資料表
Schema::create('order_product', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('order_id');
$table->unsignedBigInteger('product_id');
$table->integer('index'); // 商品在訂單中的順序
});
建立 Order
Product
兩個 model
class Order extends Model
{
public function products()
{
return $this->hasMany(Product::class)->withPivot('index');
}
}
class Product extends Model
{
public function orders()
{
return $this->belongsToMany(Order::class);
}
}
建立訂單
$order = Order::create($request['data']['meta']);
$products = $request['data']['products'];
/*
[
[10 => ['index' => 1]],
[15 => ['index' => 2]],
[11 => ['index' => 3]],
]
*/
$order->products()->**attach**($products);
attach
:建立中間表的資料,只能新增 primary id 值,以及更新 pivot table 裡的值更新訂單 (最複雜變成最簡單~)
$order = Order::create($request['data']['meta']);
$products = $request['data']['products'];
// method 1
/*
$products = [
[5 => ['index' => 1]],
[7 => ['index' => 2]],
[9 => ['index' => 3]],
]
*/
$order->products()->**sync**($products);
// method 2
/*
$products = [5, 7, 9] 只有 primary ids
*/
$order->products()->sync($products);
// method3
/*
$products = [5, 7, 9] 只有 primary ids
但同時需要更新 "更新時間"
*/
$order->products()->syncWithPivotValues($products, ['updated_at', new Carbon::()]);