:::
17-3 加入送出訂單按鈕
- 為了讓訂單能送出,我們必須在購物車界面加上<form>,至於送出的方式,可以直接利用表單方式送出,也可以利用ajax方式送出。由於後者我們已經用過好幾次,因此,這次來學學前者該如何使用。
- 修改路由
\專案\routes\web.php,加入儲存訂單的功能:Route::post('/order/store', 'OrderController@store')->name('order.store'); - 接著修改購物車模板
\專案\resources\views\cart\index.blade.php:<h1>我的購物車</h1> <form action="{{ route('order.store') }}" method="post" id="order-form"> @csrf <table class="table table-striped"> ...略... @forelse($user->carts as $cart) ...略... @empty ...略... @endforelse ...略... </table> @if(count($user->carts)) <div class="form-group row"> <label class="col-form-label col-sm-3 text-md-right">收貨地址</label> <div class="col-sm-7"> <input type="text" class="form-control" name="address" value="{{ $user->address }}"> </div> <div class="col-sm-2"> <button type="submit" class="btn btn-primary">送出訂單</button> </div> </div> @endif </form>-
首先,我們在前後加入
<form></form>使之成為一個可以送出的表單,表單的方法必須設定為post,因為屆時要儲存的store其動詞就是post(第 2 行) -
表單務必加入
@csrf,以產生csrf令牌,否則送出後,會出現419 Page Expired的訊息(第 3 行),詳情可參考:https://learnku.com/docs/laravel/5.8/csrf/3892#csrf-introduction -
接著在第 13~23 行加入預設地址及送出鈕,地址預設值由會員的地址產生,前後會先用
count()判斷購物車陣列數量,也就是判斷是否有東西,有才會顯示,避免送出空訂單。
-
- 送出訂單有幾個基本動作要執行:
- 在orders中新增一筆訂單資料
- 將購物車中的所有品項寫入order_items
- 刪除購物車中該買家的所有品項
- 最後修改最重要(也最複雜)的訂單的控制器
\專案\app\Http\Controllers\OrderController.php:use App\Order; use App\OrderItem; use App\Product; use DB; use Illuminate\Http\Request; ...略... public function store(Request $request) { $user = $request->user(); // 開啟一個資料庫交易 DB::transaction(function () use ($user, $request) { // 建立一個訂單 $order = new Order; $order->address = $request->address; $order->total = 0; $order->closed = 0; $order->user_id = $user->id; $order->save(); $total = 0; // 計算所有購物車內容的數量及價格 foreach ($request->amount as $product_id => $amount) { $product = Product::find($product_id); $item = new OrderItem; $item->order_id = $order->id; $item->product_id = $product_id; $item->amount = $amount; $item->price = $product->price; $item->save(); $total += $product->price * $amount; } // 更新訂單總金額 $order->total = $total; $order->update(); // 將下單的商品從購物車中移除 $user->carts()->delete(); }); return redirect()->route('index'); } - 第12行:先從請求,取得目前使用者(即買家)的模型資料,後面要進行關聯時會用到。
- 第14行:利用
DB::transaction();建立一個資料庫的交易,需完成裡面所有動作,交易才會成立,否則會全部作廢。- 交易詳情可參考:https://learnku.com/docs/laravel/5.8/database/3925#database-transactions
- 交易中用了一個閉包
function () use ($user, $request) {},這是閉包+引用的作法,用來傳參數給閉包的內容使用,詳情可參考:https://www.twblogs.net/a/5b84d7ab2b71775d1cd21703
- 第16-21行:我們先將訂單存起來,
total(總計)暫時先設成0,等所有購物車項目計算完再來更新這裡的值(切勿相信或使用從模板傳來的金額,因為非常容易被修改) - 第25行:利用迴圈,將所有購物車的內容計算過一遍。
$request->amount是一個陣列,其索引就是產品編號$product_id,其值就是購買數量$amount。 - 第26行:利用
product_id取得該商品資訊,我們主要是為了要取的該商品價錢 - 第27-32行:我們建立一筆訂單項目,紀錄該購物車的商品編號及數量,以及所屬的訂單編號
$order->id。 - 第33行:則是計算商品價格及數量,並累計到總價
- 第38行:利用
update()更新該訂單的總價,關於更新可以參考:https://learnku.com/docs/laravel/5.8/eloquent/3931#updates - 第41行:我們從
$user->carts()即該使用者的所有購物車中的項目,利用delete()將之全數刪除即可。 - 第44行:最後只要利用
redirect()做轉向,暫時回到首頁即可,關於redirect用法可參考:https://learnku.com/docs/laravel/5.8/helpers/3919#method-redirect
17-2 設定訂單及訂單項目的關聯
