Laravel 12 E-Commerce Project Tutorial
Implementing Checkout With Cash On Delivery (COD)
Hi everyone, welcome back to the Laravel E-Commerce Project Tutorial. In this video, we will implement the complete checkout logic for Cash on Delivery (COD), including placing the order, saving it to the database, and displaying the order confirmation page.
-
Create the `place_order` Function in `CartController`
Open your `CartController` and create a function to handle the order submission. This function validates the incoming address data (if a default address isn'tset), saves the address, saves the order details, saves each order item, saves the transaction record, and finally clears the cart and session data.
public function place_order(Request $request)
{
$user_id = Auth::user()->id;
// 1. Get or create the address
$address = Address::where("user_id", $user_id)->where("isdefault", true)->first();
if(!$address)
{
$request->validate([
"name" => "required|max:100",
"phone" => "required|numeric|digits:10",
"zip" => "required|numeric|digits:6",
"state" => "required",
"city" => "required",
"address" => "required",
"locality" => "required",
"landmark" => "required",
]);
$address = new Address();
$address->user_id = $user_id;
$address->name = $request->name;
$address->phone = $request->phone;
$address->zip = $request->zip;
$address->state = $request->state;
$address->city = $request->city;
$address->address = $request->address;
$address->locality = $request->locality;
$address->country = $request->country;
$address->landmark = $request->landmark;
$address->type = "shipping"; // Assuming new address is for shipping
$address->save();
}
// Set amounts for checkout (including coupon discounts)
$this->setAmountForCheckout();
// 2. Save the Order
$order = new Order();
$order->user_id = $user_id;
$order->subtotal = session()->get("checkout")["subtotal"];
$order->discount = session()->get("checkout")["discount"];
$order->tax = session()->get("checkout")["tax"];
$order->total = session()->get("checkout")["total"];
$order->name = $address->name;
$order->phone = $address->phone;
$order->locality = $address->locality;
$order->address = $address->address;
$order->city = $address->city;
$order->state = $address->state;
$order->country = $address->country;
$order->landmark = $address->landmark;
$order->zip = $address->zip;
$order->save();
// 3. Save Order Items
foreach(Cart::instance("cart")->content() as $item)
{
$orderItem = new OrderItem();
$orderItem->product_id = $item->id;
$orderItem->order_id = $order->id;
$orderItem->price = $item->price;
$orderItem->quantity = $item->qty;
$orderItem->options = $item->options->has("options") ? serialize($item->options->get("options")) : "";
$orderItem->rstatus = "pending";
$orderItem->save();
}
// 4. Save Transaction (COD)
$transaction = new Transaction();
$transaction->user_id = $user_id;
$transaction->order_id = $order->id;
$transaction->mode = $request->mode; // Should be "cod"
$transaction->status = "pending";
$transaction->save();
// 5. Clear Cart and Session
Cart::instance("cart")->destroy();
session()->forget("coupon");
session()->forget("discounts");
session()->forget("checkout");
// 6. Redirect to Order Complete page
return redirect()->route("order.complete",["order_id" => $order->id]);
} -
Define Routes for Order Placement and Confirmation
Add the following routes to your `web.php` file:
// Route for processing the order submission
Route::post("/order/place",[CartController::class,"place_order"])->name("order.place");
// Route for displaying the order confirmation page
Route::get("/order/complete/{order_id}",[CartController::class,"order_complete"])->name("order.complete"); -
Create the `order_complete` Function
In `CartController`, create a simple function to retrieve the confirmed order and load the success view.
public function order_complete($order_id)
{
$order = Order::find($order_id);
return view("order-complete",compact("order"));
} -
Create the Order Complete View (`order-complete.blade.php`)
Create the confirmation page view. This page displays the order details (invoice) and a success message. It also includes a JavaScript function to print the invoice.
<x-app-layout>
<!-- Main Content: Order Details (Invoice) and Success Message -->
<!-- Success Message Display -->
<div class="order-complete">
<div class="order-complete_message">
<svg width="80" height="80" viewBox="0 0 80 80" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="40" cy="40" r="40" fill="#B9A16B" />
<path d="M52.9743 35.7612C52.9743 35.3426 52.8069 34.9241 52.5856 34.6228L50.2288 32.346C49.9275 32.0446 49.5089 ..." />
</svg>
<h3>Your order is completed!</h3>
<p>Thank you. Your order has been received.</p>
<a href="{{ route("shop.index") }}" class="btn btn-info mt-5">Shop More</a>
</div>
</div>
<!-- Invoice Section (to be styled/populated with $order details) -->
<div id="invoice">
<!-- ... Invoice HTML Structure here, using $order and $order->orderItems ... -->
<button class="btn btn-dark" onclick="printInvoice("invoice")">Print Invoice</button>
</div>
@push("scripts")
<script>
function printInvoice(divName) {
var printContents = document.getElementById(divName).innerHTML;
var originalContents = document.body.innerHTML;
document.body.innerHTML = printContents;
window.print();
document.body.innerHTML = originalContents;
}
</script>
@endpush
</x-app-layout>
Verification and Testing 🛒
Go to the checkout page, fill in the shipping address (if necessary), select Cash on Delivery, and click Place Order. You should be redirected to the `/order/complete/{order_id}` page, see the success message, and have the option to print your invoice.
