:::

17-3 加入送出訂單按鈕

  1. 為了讓訂單能送出,我們必須在購物車界面加上<form>,至於送出的方式,可以直接利用表單方式送出,也可以利用ajax方式送出。由於後者我們已經用過好幾次,因此,這次來學學前者該如何使用。
  2. 修改路由\專案\routes\web.php,加入儲存訂單的功能:
    Route::post('/order/store', 'OrderController@store')->name('order.store');
  3. 接著修改購物車模板\專案\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()判斷購物車陣列數量,也就是判斷是否有東西,有才會顯示,避免送出空訂單。

  4. 送出訂單有幾個基本動作要執行:
    1. 在orders中新增一筆訂單資料
    2. 將購物車中的所有品項寫入order_items
    3. 刪除購物車中該買家的所有品項
  5. 最後修改最重要(也最複雜)的訂單的控制器\專案\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');
    
    }
  6. 第12行:先從請求,取得目前使用者(即買家)的模型資料,後面要進行關聯時會用到。
  7. 第14行:利用DB::transaction();建立一個資料庫的交易,需完成裡面所有動作,交易才會成立,否則會全部作廢。
    1. 交易詳情可參考:https://learnku.com/docs/laravel/5.8/database/3925#database-transactions
    2. 交易中用了一個閉包function () use ($user, $request) {},這是閉包+引用的作法,用來傳參數給閉包的內容使用,詳情可參考:https://www.twblogs.net/a/5b84d7ab2b71775d1cd21703
  8. 第16-21行:我們先將訂單存起來,total(總計)暫時先設成0,等所有購物車項目計算完再來更新這裡的值(切勿相信或使用從模板傳來的金額,因為非常容易被修改)
  9. 第25行:利用迴圈,將所有購物車的內容計算過一遍。$request->amount是一個陣列,其索引就是產品編號$product_id,其值就是購買數量$amount
  10. 第26行:利用product_id取得該商品資訊,我們主要是為了要取的該商品價錢
  11. 第27-32行:我們建立一筆訂單項目,紀錄該購物車的商品編號及數量,以及所屬的訂單編號$order->id
  12. 第33行:則是計算商品價格及數量,並累計到總價
  13. 第38行:利用update()更新該訂單的總價,關於更新可以參考:https://learnku.com/docs/laravel/5.8/eloquent/3931#updates
  14. 第41行:我們從$user->carts()即該使用者的所有購物車中的項目,利用delete()將之全數刪除即可。
  15. 第44行:最後只要利用redirect()做轉向,暫時回到首頁即可,關於redirect用法可參考:https://learnku.com/docs/laravel/5.8/helpers/3919#method-redirect

到GitHub觀看此單元程式異動


:::

書籍目錄

展開 | 闔起

http%3A%2F%2Fcampus-xoops.tn.edu.tw%2Fmodules%2Ftad_book3%2Fpage.php%3Ftbsn%3D43%26tbdsn%3D1453

計數器

今天: 365365365
昨天: 2212221222122212
總計: 7604131760413176041317604131760413176041317604131