Step 6 – Building the Shopping Cart System in Laravel

Making your store interactive

Up to this point, your store can display products beautifully, and customers can browse them. But browsing alone won’t pay the bills — your site needs a way for users to collect products they want to buy, just like a real-world shopping basket.

This is where the shopping cart system comes in. It’s the first real piece of “e-commerce logic” that connects browsing with purchasing. Without it, your store is just a catalog.

In this part, you’ll learn how to design and build a simple yet flexible shopping cart system using Laravel. We’ll cover both the conceptual side (how a cart works behind the scenes) and the technical side (building it with Laravel sessions).


🎯 What We’ll Build

Let’s clearly define our goals so you have a mental roadmap:

  • Each product detail page has an “Add to Cart” button.
  • Users can view a cart page showing all selected products, quantities, and totals.
  • Users can update quantities or remove items.
  • Cart data will be stored in sessions (for now — database cart comes later).
  • We will write clean, reusable cart logic so you can expand it later during checkout.

This step will make your store feel alive and interactive.


🧠 How Shopping Carts Work (Behind the Scenes)

Before writing code, it helps to understand the mechanics:

  • A cart is basically a collection (array) of products with quantities.
  • It lives temporarily in session storage until the user checks out or leaves.
  • When a user adds a product, we check if it’s already in the cart:
    • If yes, increase the quantity
    • If no, add a new item entry
  • When showing the cart, we calculate the subtotal, tax, and total.

This concept is simple but powerful — and it will become the base for our checkout system later.


⚙️ Step 1 : Setting Up Routes

Let’s first plan the user flows:

  • /cart – Show the shopping cart.
  • /cart/add/{id} – Add a product to the cart.
  • /cart/remove/{id} – Remove a product from the cart.
  • /cart/update/{id} – Update quantity.

Open routes/web.php and add:

use App\Http\Controllers\CartController;

Route::get('/cart', [CartController::class, 'index'])->name('cart.index');
Route::post('/cart/add/{id}', [CartController::class, 'add'])->name('cart.add');
Route::post('/cart/update/{id}', [CartController::class, 'update'])->name('cart.update');
Route::delete('/cart/remove/{id}', [CartController::class, 'remove'])->name('cart.remove');

This gives you all the endpoints you need to interact with the cart.


⚙️ Step 2: Create the CartController

Now build the logic behind those routes.

php artisan make:controller CartController

Open app/Http/Controllers/CartController.php and add:

namespace App\Http\Controllers;

use App\Models\Product;
use Illuminate\Http\Request;

class CartController extends Controller
{
    public function index()
    {
        $cart = session()->get('cart', []);
        $total = collect($cart)->sum(fn($item) => $item['price'] * $item['quantity']);

        return view('cart.index', compact('cart','total'));
    }

    public function add($id)
    {
        $product = Product::findOrFail($id);
        $cart = session()->get('cart', []);

        if(isset($cart[$id])) {
            $cart[$id]['quantity']++;
        } else {
            $cart[$id] = [
                'name' => $product->name,
                'price' => $product->price,
                'quantity' => 1,
                'image' => $product->image
            ];
        }

        session()->put('cart', $cart);

        return redirect()->back()->with('success','Product added to cart!');
    }

    public function update(Request $request, $id)
    {
        $cart = session()->get('cart', []);
        if(isset($cart[$id])) {
            $cart[$id]['quantity'] = $request->quantity;
            session()->put('cart', $cart);
        }

        return redirect()->route('cart.index');
    }

    public function remove($id)
    {
        $cart = session()->get('cart', []);
        if(isset($cart[$id])) {
            unset($cart[$id]);
            session()->put('cart', $cart);
        }

        return redirect()->route('cart.index');
    }
}

What this does:

  • We use Laravel’s session() to store the cart array.
  • add() checks if the product exists in the cart before adding.
  • update() changes the quantity.
  • remove() deletes an item completely.
  • index() sends cart data to the view with a computed total.

This is a clean, self-contained system — no database needed yet.


⚙️ Step 3: Adding the “Add to Cart” Button

Let’s make the button on your product detail page actually do something.

In resources/views/shop/show.blade.php replace the Add to Cart button:

<form action="{{ route('cart.add', $product->id) }}" method="POST">
  @csrf
  <button type="submit" class="btn btn-success btn-lg mt-3">
    Add to Cart
  </button>
</form>

Now when someone clicks it, the product goes into their cart session.


⚙️ Step 4: Building the Cart Page View

Create a new file resources/views/cart/index.blade.php:

@extends('layouts.app')

@section('content')
<div class="container">
  <h1 class="mb-4">Your Shopping Cart</h1>

  @if(session('success'))
    <div class="alert alert-success">{{ session('success') }}</div>
  @endif

  @if(empty($cart))
    <p>Your cart is empty. <a href="{{ route('shop.index') }}">Continue shopping</a></p>
  @else
    <table class="table table-bordered">
      <thead>
        <tr>
          <th>Product</th>
          <th>Price</th>
          <th>Quantity</th>
          <th>Subtotal</th>
          <th></th>
        </tr>
      </thead>
      <tbody>
        @foreach($cart as $id => $item)
          <tr>
            <td>
              <img src="{{ asset('storage/'.$item['image']) }}" width="50" class="me-2">
              {{ $item['name'] }}
            </td>
            <td>${{ $item['price'] }}</td>
            <td>
              <form action="{{ route('cart.update',$id) }}" method="POST" class="d-flex">
                @csrf
                <input type="number" name="quantity" value="{{ $item['quantity'] }}" min="1" class="form-control form-control-sm w-50 me-2">
                <button class="btn btn-sm btn-primary">Update</button>
              </form>
            </td>
            <td>${{ $item['price'] * $item['quantity'] }}</td>
            <td>
              <form action="{{ route('cart.remove',$id) }}" method="POST">
                @csrf @method('DELETE')
                <button class="btn btn-sm btn-danger">Remove</button>
              </form>
            </td>
          </tr>
        @endforeach
      </tbody>
    </table>

    <div class="text-end">
      <h4>Total: ${{ $total }}</h4>
      <a href="#" class="btn btn-success btn-lg mt-3">Proceed to Checkout</a>
    </div>
  @endif
</div>
@endsection

What’s happening here:

  • Displays all cart items with images and quantities.
  • Lets users update or remove items directly.
  • Shows running total at the bottom.
  • Handles empty cart gracefully.

⚙️ Step 5 : Session Tips and Common Gotchas

A few lessons learned from real projects:

  • Session data disappears on browser close — This is okay for now, but later we’ll store carts in the database for logged-in users.
  • Always validate quantity input — Make sure users can’t set quantity to zero or negative.
  • Use flash messages (with('success','...')) for user feedback. It makes the site feel more interactive.
  • Clear session on checkout — Don’t forget this later when building the order system.

💡 Personal Notes & UX Suggestions

Here are a few insights from building carts on real Laravel projects:

  • Users expect a mini cart icon in the navbar showing the number of items. You can do this by counting session items in your layout.
  • Add a “Continue Shopping” button on the cart page to bring users back.
  • Keep cart actions fast and simple. Avoid page reloads if possible — you can later upgrade this to use AJAX or Alpine.js for instant updates.
  • For mobile users, make sure the table scrolls horizontally using Bootstrap’s .table-responsive wrapper.

Even small UX touches make your cart feel professional.


✅ Summary

At this point, your Laravel e-commerce application has:

  • A fully functional session-based shopping cart
  • Add, update, and remove item features
  • A clean and responsive cart page
  • A smooth user experience to keep shoppers engaged

This is a huge milestone. Your store has gone from static product listings to a dynamic interactive shop where customers can collect products for checkout.


🚀 Coming Next

In Step 7, we’ll move from the cart to the checkout system — where customers enter their details, confirm their order, and where you’ll store the order data in the database.

This is where your e-commerce app becomes a real store.

Leave a Comment