Laravel Livewire Shopping Cart Step by Step Example

In this section, we’ll implement shopping cart functionality in Laravel Livewire using the Shopping Cart package. Livewire is used for building dynamic interfaces simply, without leaving the comfort of Laravel.

It’s very simple and easy to start with, especially if you’re creating a small e-commerce project. In this example, I’ve used Tailwind CSS, but you can also use Bootstrap if you prefer.

Set Up Laravel Project

Installing a fresh new laravel application, so head over to the terminal, type the command, and create a new laravel app.

composer create-project --prefer-dist laravel/laravel livewire-cart

Set Up Database Details in ENV

Now, you have to connect the laravel app to the database, hence open the .env configuration file and add the database credentials as suggested below.

.env
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=database_name
DB_USERNAME=database_user_name
DB_PASSWORD=database_password

Setup laravelshoppingcart package

composer require "darryldecode/cart"

Open config/app.php and add this line to your Service Providers Array.

Darryldecode\Cart\CartServiceProvider::class

Open config/app.php and add this line to your Aliases.

'Cart' => Darryldecode\Cart\Facades\CartFacade::class

Optional configuration file (useful if you plan to have full control)

php artisan vendor:publish --provider="Darryldecode\Cart\CartServiceProvider" --tag="config"

Install Livewire

composer require livewire/livewire

Include the JavaScript (on every page that will be using Livewire).

...
  @livewireStyles
</head>
<body>
  ...

  @livewireScripts
</body>
</html>

Create Product Model with Migration

php artisan make:model Product -m 

product migration file.

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateProductsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('products', function (Blueprint $table) {
            $table->id();
            $table->string('name');
            $table->double('price');
            $table->text('description');
            $table->string('image');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('products');
    }
}

product model file.

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Product extends Model
{
    use HasFactory;
    protected $fillable = [
        'name',
        'price',
        'image',
        'description',
    ];
}

Create Product Seeder

php artisan make:seeder ProductSeeder

Now add dummy data in seeder.

<?php

namespace Database\Seeders;

use App\Models\Product;
use Illuminate\Database\Seeder;

class ProductSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        Product::create([
            'name' => 'Watch',
            'price' => 250,
            'description' => 'Good watch',
            'image' => 'https://images.unsplash.com/photo-1523275335684-37898b6baf30?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=989&q=80'
        ]);
        Product::create([
            'name' => 'Bag',
            'price' => 350,
            'description' => 'Good Bag',
            'image' => 'https://images.unsplash.com/photo-1491637639811-60e2756cc1c7?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=669&q=80'
        ]);
        Product::create([
            'name' => 'perfume',
            'price' => 100,
            'description' => 'Good perfume',
            'image' => 'https://images.unsplash.com/photo-1528740561666-dc2479dc08ab?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=1868&q=80'
        ]);
    }
}

Now create controller and routes.

php artisan make:controller ProductController 

Create Routes in web.php

<?php

use App\Http\Controllers\CartController;
use App\Http\Controllers\ProductController;
use Illuminate\Support\Facades\Route;

/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/

Route::get('/', [ProductController::class, 'productList'])->name('products.list');
Route::get('cart', [ProductController::class, 'cartList'])->name('cart.list');
Route::post('cart', [ProductController::class, 'addToCart'])->name('cart.store');

Add Code Logic In Controller

app/Http/Controllers/ProductController.php

<?php

namespace App\Http\Controllers;

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

class ProductController extends Controller
{
    public function productList()
    {
        $products = Product::all();

        return view('products', compact('products'));
    }

    public function cartList()
    {
        return view('cart');
    }

    public function addToCart(Request $request)
    {
        \Cart::add([
            'id' => $request->id,
            'name' => $request->name,
            'price' => $request->price,
            'quantity' => $request->quantity,
            'attributes' => array(
                'image' => $request->image,
            )
        ]);
        session()->flash('success', 'Product is Added to Cart Successfully !');

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

Create View Files

do not forget to add @livewireStyles and @livewireScripts

resources/views/layouts/frontend.blade.php

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Add to cart with livewire</title>
    <link href="https://unpkg.com/tailwindcss@^2/dist/tailwind.min.css" rel="stylesheet">
    @livewireStyles
</head>
<body>
    <div  class="bg-white">
        <header>
            <div class="container px-6 py-3 mx-auto">
                <div class="flex items-center justify-between">
                    
                    
                    <div class="flex items-center justify-end w-full">
                        <button" class="mx-4 text-gray-600 focus:outline-none sm:mx-0">
                            
                        </button>
                    </div>
                </div>
                <nav  class="p-6 mt-4 text-white bg-black sm:flex sm:justify-center sm:items-center">
                    <div class="flex flex-col sm:flex-row">
                        <a class="mt-3 hover:underline sm:mx-3 sm:mt-0" href="/">Shop</a>
                        <a href="{{ route('cart.list') }}" class="flex items-center">
                          profile  
                        </a>
                        
                    </div>
                </nav>
            </div>
        </header>
        
        <main class="my-8">
            @yield('content')
        </main>
    
    </div>
    @livewireScripts
</body>
</html>

resources/views/products.blade.php

@extends('layouts.frontend')

@section('content')
    <div class="container px-6 mx-auto">
        <h3 class="text-2xl font-medium text-gray-700">Product List</h3>
        <div class="grid grid-cols-1 gap-6 mt-6 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4">
            @foreach ($products as $product)
            <div class="w-full max-w-sm mx-auto overflow-hidden rounded-md shadow-md">
                <img src="{{ url($product->image) }}" alt="" class="w-full max-h-60">
                <div class="flex items-end justify-end w-full bg-cover">
                    
                </div>
                <div class="px-5 py-3">
                    <h3 class="text-gray-700 uppercase">{{ $product->name }}</h3>
                    <span class="mt-2 text-gray-500">${{ $product->price }}</span>
                    <form action="{{ route('cart.store') }}" method="POST" enctype="multipart/form-data">
                        @csrf
                        <input type="hidden" value="{{ $product->id }}" name="id">
                        <input type="hidden" value="{{ $product->name }}" name="name">
                        <input type="hidden" value="{{ $product->price }}" name="price">
                        <input type="hidden" value="{{ $product->image }}"  name="image">
                        <input type="hidden" value="1" name="quantity">
                        <button class="px-4 py-2 text-white bg-blue-800 rounded">Add To Cart</button>
                    </form>
                </div>
                
            </div>
            @endforeach
        </div>
    </div>
@endsection

Run Livewire Command

php artisan make:livewire CartList

COMPONENT CREATED 🤙

CLASS: app/Http/Livewire/CartLit.php

VIEW: resources/views/livewire/cart-list.blade.php

php artisan make:livewire CartUpdate

COMPONENT CREATED 🤙

CLASS: app/Http/Livewire/CartUpdate.php

VIEW: resources/views/livewire/cart-update.blade.php

app/Http/Livewire/CartList.php

<?php

namespace App\Http\Livewire;

use Livewire\Component;


class CartList extends Component
{
    protected $listeners = ['cartUpdated' => '$refresh'];
    public $cartItems = [];

    public function removeCart($id)
    {
        \Cart::remove($id);

        session()->flash('success', 'Item has removed !');
    }

    public function clearAllCart()
    {
        \Cart::clear();

        session()->flash('success', 'All Item Cart Clear Successfully !');
    }

    public function render()
    {
        $this->cartItems = \Cart::getContent()->toArray();

        return view('livewire.cart-list');
    }
}

app/Http/Livewire/CartUpdate.php

<?php

namespace App\Http\Livewire;

use Livewire\Component;

class CartUpdate extends Component
{
    public $cartItems = [];
    public $quantity = 1;

    public function mount($item)
    {
        $this->cartItems = $item;

        $this->quantity = $item['quantity'];
    }

    public function updateCart()
    {
        \Cart::update($this->cartItems['id'], [
            'quantity' => [
                'relative' => false,
                'value' => $this->quantity
            ]
        ]);

        $this->emit('cartUpdated');
    }

    public function render()
    {
        return view('livewire.cart-update');
    }
}

resources/views/cart.blade.php

@extends('layouts.frontend')

@section('content')

<main class="my-8">
    <div class="container px-6 mx-auto">
        <div class="flex justify-center my-6">
            <div class="flex flex-col w-full p-8 text-gray-800 bg-white shadow-lg pin-r pin-y md:w-4/5 lg:w-4/5">

                <livewire:cart-list />
            </div>
        </div>
    </div>
</main>
@endsection

resources/views/livewire/cart-update.blade.php

<div>
    <input wire:model="quantity" type="number" min="1" max="5" wire:change="updateCart" class="text-center bg-gray-100">
</div>

resources/views/livewire/cart-list.blade.php

<div>
    @if ($message = Session::get('success'))
    <div class="p-4 mb-3 bg-green-400 rounded">
        <p class="text-green-800">{{ $message }}</p>
    </div>
    @endif
    <h3 class="text-3xl text-bold">
        Total {{ Cart::getTotalQuantity()}} Cart
    </h3>
    <div class="flex-1">
        <table class="w-full text-sm lg:text-base" cellspacing="0">
            <thead>
                <tr class="h-12 uppercase">
                    <th class="hidden md:table-cell"></th>
                    <th class="text-left">Name</th>
                    <th class="pl-5 text-left lg:text-right lg:pl-0">
                        <span class="lg:hidden" title="Quantity">Qtd</span>
                        <span class="hidden lg:inline">Quantity</span>
                    </th>
                    <th class="hidden text-right md:table-cell"> price</th>
                    <th class="hidden text-right md:table-cell"> Remove </th>
                </tr>
            </thead>
            <tbody>
                @foreach ($cartItems as $item)
                <tr>
                    <td class="hidden pb-4 md:table-cell">
                        <a href="#">
                            <img src="{{ $item['attributes']['image'] }}" class="w-20 rounded" alt="Thumbnail">
                        </a>
                    </td>
                    <td>
                        <a href="#">
                            <p class="mb-2 md:ml-4">{{ $item['name'] }}</p>
                        </a>
                    </td>
                    <td class="justify-center mt-6 md:justify-end md:flex">
                        <div class="h-10 w-28">
                            <div class="relative flex flex-row w-full h-8">
                                <livewire:cart-update :item="$item" :key="$item['id']" />
                            </div>
                        </div>
                    </td>
                    <td class="hidden text-right md:table-cell">
                        <span class="text-sm font-medium lg:text-base">
                            ${{ $item['price'] }}
                        </span>
                    </td>
                    <td class="hidden text-right md:table-cell">
                        <a href="#" class="px-4 py-2 text-white bg-red-600" wire:click.prevent="removeCart('{{$item['id']}}')">x</a>
                    </td>
                </tr>
                @endforeach

            </tbody>
        </table>
        <div>
            Total: ${{ Cart::getTotal() }}
        </div>
        <div class="mt-5">
            <a href="#" class="px-6 py-2 text-red-800 bg-red-300" wire:click.prevent="clearAllCart">Remove All Cart</a>
        </div>

    </div>
</div>

Now All is Done 🎉

just run server and check

http://localhost:8000/
saim ansari
saim ansari

I'm Saim Ansari, a full-stack developer with 4+ years of hands-on experience who thrives on building web applications that leave a lasting impression. When it comes to tech, I'm particularly adept at Laravel, React, Tailwind CSS, and the Tall Stack