Backend Development

Creating a Shopping Cart With Laravel

Creating a Shopping Cart With Laravel

In this tutorial i will demonstrate how to create a shopping cart with php using laravel framework. we will be using laravel 5.5 but you can also use any other version.

 

Requirements:

  • Apache or IIS with PHP >= 5.6.4 .
  • Twitter bootstrap.

 

Installation

In your local development path type this command to install laravel 5.5.

composer create-project laravel/laravel shopping-cart  "5.5.*" --prefer-dist

After successful installation be sure that there is a “.env” file in the root path of the application. If not then take a copy of “.env.example” and rename it to “.env” then in type this command in the terminal.

php artisan key:generate

Now laravel successfully installed and you can be sure by visiting http://localhost/shopping-cart/public/.

 

Preparing Database

Every shopping cart must have a products table so we will create it right now.

Go to phpmyadmin and create a new database called “shopping_cart”. Then go to your .env file and set your database name and credentials like this:

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=shopping_cart
DB_USERNAME=<your db username>
DB_PASSWORD=<your db password>

 

Next we will be using laravel migration to create tables so ype this command in terminal.

php artisan make:model Product -m

The above command will create a Product model and -m for migration.

Now go to database>migrations and open up the migration we just created for products table.

<?php

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

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

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

We will be adding some more fields to the up() function so add this code after $table->increments(‘id’)

$table->string("name", 255)->nullable();
$table->text("description")->nullable();
$table->string("photo", 255)->nullable();
$table->decimal("price", 6, 2);

Now migrate your tables by this command:

php artisan migrate

Now if you go to phpmyadmin. This is our database might look like after migration

Now let’s create a Seeder to populate our products table with some data to work with. Run this command to generate a seeder.

php artisan make:seed ProductsSeeder

Go to database>seeds>ProductsSeeder. Then inside run() function add this code.

DB::table('products')->insert([
           'name' => 'Samsung Galaxy S9',
           'description' => 'A brand new, sealed Lilac Purple Verizon Global Unlocked Galaxy S9 by Samsung. This is an upgrade. Clean ESN and activation ready.',
           'photo' => 'https://i.ebayimg.com/00/s/ODY0WDgwMA==/z/9S4AAOSwMZRanqb7/$_35.JPG?set_id=89040003C1',
           'price' => 698.88
        ]);

        DB::table('products')->insert([
            'name' => 'Apple iPhone X',
            'description' => 'GSM & CDMA FACTORY UNLOCKED! WORKS WORLDWIDE! FACTORY UNLOCKED. iPhone x 64gb. iPhone 8 64gb. iPhone 8 64gb. iPhone X with iOS 11.',
            'photo' => 'https://i.ebayimg.com/00/s/MTYwMFg5OTU=/z/9UAAAOSwFyhaFXZJ/$_35.JPG?set_id=89040003C1',
            'price' => 983.00
        ]);

        DB::table('products')->insert([
            'name' => 'Google Pixel 2 XL',
            'description' => 'New condition
• No returns, but backed by eBay Money back guarantee',
            'photo' => 'https://i.ebayimg.com/00/s/MTYwMFg4MzA=/z/G2YAAOSwUJlZ4yQd/$_35.JPG?set_id=89040003C1',
            'price' => 675.00
        ]);

        DB::table('products')->insert([
            'name' => 'LG V10 H900',
            'description' => 'NETWORK Technology GSM. Protection Corning Gorilla Glass 4. MISC Colors Space Black, Luxe White, Modern Beige, Ocean Blue, Opal Blue. SAR EU 0.59 W/kg (head).',
            'photo' => 'https://i.ebayimg.com/00/s/NjQxWDQyNA==/z/VDoAAOSwgk1XF2oo/$_35.JPG?set_id=89040003C1',
            'price' => 159.99
        ]);

        DB::table('products')->insert([
            'name' => 'Huawei Elate',
            'description' => 'Cricket Wireless - Huawei Elate. New Sealed Huawei Elate Smartphone.',
            'photo' => 'https://ssli.ebayimg.com/images/g/aJ0AAOSw7zlaldY2/s-l640.jpg',
            'price' => 68.00
        ]);

        DB::table('products')->insert([
            'name' => 'HTC One M10',
            'description' => 'The device is in good cosmetic condition and will show minor scratches and/or scuff marks.',
            'photo' => 'https://i.ebayimg.com/images/g/u-kAAOSw9p9aXNyf/s-l500.jpg',
            'price' => 129.99
        ]);

Now run this command to seed your data.

php artisan db:seed --class=ProductsSeeder

Our products table now might look like.

 

Controller & Views

Let’s create a controller for our products and cart called “ProductsController”.

php artisan make:controller ProductsController

<?php

namespace App\Http\Controllers;

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

class ProductsController extends Controller
{

}

Now these actions in the above controller as shown:

    public function index()
    {
        return view('products');
    }

    public function cart()
    {
        return view('cart');
    }
    public function addToCart($id)
    {

    }

In the above code we created two actions for our products and cart pages and one action for add to cart.

Next we will create three views with dummy data:

  • layout.blade.php: this is the main layout view.
  • products.blade.php: this is the view that will display our products.
  • cart.blade.php: this is the cart view.

In the layout.blade.php copy and paste this code.

<!DOCTYPE html>
<html>
<head>

    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

    <title>@yield('title')</title>

    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css">
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css">
    <link rel="stylesheet" type="text/css" href="{{ asset('css/style.css') }}">

    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"></script>

</head>
<body>

<div class="container">

    <div class="row">
        <div class="col-lg-12 col-sm-12 col-12 main-section">
            <div class="dropdown">
                <button type="button" class="btn btn-info" data-toggle="dropdown">
                    <i class="fa fa-shopping-cart" aria-hidden="true"></i> Cart <span class="badge badge-pill badge-danger">3</span>
                </button>
                <div class="dropdown-menu">
                    <div class="row total-header-section">
                        <div class="col-lg-6 col-sm-6 col-6">
                            <i class="fa fa-shopping-cart" aria-hidden="true"></i> <span class="badge badge-pill badge-danger">3</span>
                        </div>
                        <div class="col-lg-6 col-sm-6 col-6 total-section text-right">
                            <p>Total: <span class="text-info">$2,978.24</span></p>
                        </div>
                    </div>
                    <div class="row cart-detail">
                        <div class="col-lg-4 col-sm-4 col-4 cart-detail-img">
                            <img src="https://images-na.ssl-images-amazon.com/images/I/811OyrCd5hL._SX425_.jpg">
                        </div>
                        <div class="col-lg-8 col-sm-8 col-8 cart-detail-product">
                            <p>Sony DSC-RX100M..</p>
                            <span class="price text-info"> $250.22</span> <span class="count"> Quantity:01</span>
                        </div>
                    </div>
                    <div class="row cart-detail">
                        <div class="col-lg-4 col-sm-4 col-4 cart-detail-img">
                            <img src="https://cdn2.gsmarena.com/vv/pics/blu/blu-vivo-48-1.jpg">
                        </div>
                        <div class="col-lg-8 col-sm-8 col-8 cart-detail-product">
                            <p>Vivo DSC-RX100M..</p>
                            <span class="price text-info"> $500.40</span> <span class="count"> Quantity:01</span>
                        </div>
                    </div>
                    <div class="row cart-detail">
                        <div class="col-lg-4 col-sm-4 col-4 cart-detail-img">
                            <img src="https://static.toiimg.com/thumb/msid-55980052,width-640,resizemode-4/55980052.jpg">
                        </div>
                        <div class="col-lg-8 col-sm-8 col-8 cart-detail-product">
                            <p>Lenovo DSC-RX100M..</p>
                            <span class="price text-info"> $445.78</span> <span class="count"> Quantity:01</span>
                        </div>
                    </div>
                    <div class="row">
                        <div class="col-lg-12 col-sm-12 col-12 text-center checkout">
                            <a href="{{ url('cart') }}" class="btn btn-primary btn-block">View all</a>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>

<div class="container page">
    @yield('content')
</div>


@yield('scripts')

</body>
</html>

As shown in the above code we have included bootstrap and jquery and the main style.css file and in the template header we displayed the cart icon along with sample dummy data.

 

products.blade.php

@extends('layout')

@section('title', 'Products')

@section('content')

    <div class="container products">

        <div class="row">

            <div class="col-xs-18 col-sm-6 col-md-3">
                <div class="thumbnail">
                    <img src="http://placehold.it/500x300" alt="">
                    <div class="caption">
                        <h4>Product name</h4>
                        <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Facere, soluta, eligendi doloribus sunt minus amet sit debitis repellat. Consectetur, culpa itaque odio similique suscipit</p>
                        <p><strong>Price: </strong> 567.7$</p>
                        <p class="btn-holder"><a href="#" class="btn btn-warning btn-block text-center" role="button">Add to cart</a> </p>
                    </div>
                </div>
            </div>

            <div class="col-xs-18 col-sm-6 col-md-3">
                <div class="thumbnail">
                    <img src="http://placehold.it/500x300" alt="">
                    <div class="caption">
                        <h4>Product name</h4>
                        <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Facere, soluta, eligendi doloribus sunt minus amet sit debitis repellat. Consectetur, culpa itaque odio similique suscipit</p>
                        <p><strong>Price: </strong> 567.7$</p>
                        <p class="btn-holder"><a href="#" class="btn btn-warning btn-block text-center" role="button">Add to cart</a> </p>
                    </div>
                </div>
            </div>

            <div class="col-xs-18 col-sm-6 col-md-3">
                <div class="thumbnail">
                    <img src="http://placehold.it/500x300" alt="">
                    <div class="caption">
                        <h4>Product name</h4>
                        <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Facere, soluta, eligendi doloribus sunt minus amet sit debitis repellat. Consectetur, culpa itaque odio similique suscipit</p>
                        <p><strong>Price: </strong> 567.7$</p>
                        <p class="btn-holder"><a href="#" class="btn btn-warning btn-block text-center" role="button">Add to cart</a> </p>
                    </div>
                </div>
            </div>

            <div class="col-xs-18 col-sm-6 col-md-3">
                <div class="thumbnail">
                    <img src="http://placehold.it/500x300" alt="">
                    <div class="caption">
                        <h4>Product name</h4>
                        <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Facere, soluta, eligendi doloribus sunt minus amet sit debitis repellat. Consectetur, culpa itaque odio similique suscipit</p>
                        <p><strong>Price: </strong> 567.7$</p>
                        <p class="btn-holder"><a href="#" class="btn btn-warning btn-block text-center" role="button">Add to cart</a> </p>
                    </div>
                </div>
            </div>

        </div><!-- End row -->

    </div>

@endsection

 

cart.blade.php

@extends('layout')

@section('title', 'Cart')

@section('content')

    <table id="cart" class="table table-hover table-condensed">
        <thead>
        <tr>
            <th style="width:50%">Product</th>
            <th style="width:10%">Price</th>
            <th style="width:8%">Quantity</th>
            <th style="width:22%" class="text-center">Subtotal</th>
            <th style="width:10%"></th>
        </tr>
        </thead>
        <tbody>
        <tr>
            <td data-th="Product">
                <div class="row">
                    <div class="col-sm-3 hidden-xs"><img src="http://placehold.it/100x100" alt="..." class="img-responsive"/></div>
                    <div class="col-sm-9">
                        <h4 class="nomargin">Product 1</h4>
                        <p>Quis aute iure reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Lorem ipsum dolor sit amet.</p>
                    </div>
                </div>
            </td>
            <td data-th="Price">$1.99</td>
            <td data-th="Quantity">
                <input type="number" class="form-control text-center" value="1">
            </td>
            <td data-th="Subtotal" class="text-center">1.99</td>
            <td class="actions" data-th="">
                <button class="btn btn-info btn-sm"><i class="fa fa-refresh"></i></button>
                <button class="btn btn-danger btn-sm"><i class="fa fa-trash-o"></i></button>
            </td>
        </tr>
        </tbody>
        <tfoot>
        <tr class="visible-xs">
            <td class="text-center"><strong>Total 1.99</strong></td>
        </tr>
        <tr>
            <td><a href="{{ url('/') }}" class="btn btn-warning"><i class="fa fa-angle-left"></i> Continue Shopping</a></td>
            <td colspan="2" class="hidden-xs"></td>
            <td class="hidden-xs text-center"><strong>Total $1.99</strong></td>
        </tr>
        </tfoot>
    </table>

@endsection

 

style.css

.main-section{
    background-color: #F8F8F8;
}
.dropdown{
    float:right;
    padding-right: 30px;
}
.btn{
    border:0px;
    margin:10px 0px;
    box-shadow:none !important;
}
.dropdown .dropdown-menu{
    padding:20px;
    top:30px !important;
    width:350px !important;
    left:-110px !important;
    box-shadow:0px 5px 30px black;
}
.total-header-section{
    border-bottom:1px solid #d2d2d2;
}
.total-section p{
    margin-bottom:20px;
}
.cart-detail{
    padding:15px 0px;
}
.cart-detail-img img{
    width:100%;
    height:100%;
    padding-left:15px;
}
.cart-detail-product p{
    margin:0px;
    color:#000;
    font-weight:500;
}
.cart-detail .price{
    font-size:12px;
    margin-right:10px;
    font-weight:500;
}
.cart-detail .count{
    color:#C2C2DC;
}
.checkout{
    border-top:1px solid #d2d2d2;
    padding-top: 15px;
}
.checkout .btn-primary{
    border-radius:50px;
    height:50px;
}
.dropdown-menu:before{
    content: " ";
    position:absolute;
    top:-20px;
    right:50px;
    border:10px solid transparent;
    border-bottom-color:#fff;
}

.thumbnail {
    position: relative;
    padding: 0px;
    margin-bottom: 20px;
}

.thumbnail img {
    width: 100%;
}

.thumbnail .caption{
    margin: 7px;
}

.page {
    margin-top: 50px;
}

.btn-holder{
    text-align: center;
}

.table>tbody>tr>td, .table>tfoot>tr>td{
    vertical-align: middle;
}
@media screen and (max-width: 600px) {
    table#cart tbody td .form-control{
        width:20%;
        display: inline !important;
    }
    .actions .btn{
        width:36%;
        margin:1.5em 0;
    }

    .actions .btn-info{
        float:left;
    }
    .actions .btn-danger{
        float:right;
    }

    table#cart thead { display: none; }
    table#cart tbody td { display: block; padding: .6rem; min-width:320px;}
    table#cart tbody tr td:first-child { background: #333; color: #fff; }
    table#cart tbody td:before {
        content: attr(data-th); font-weight: bold;
        display: inline-block; width: 8rem;
    }



    table#cart tfoot td{display:block; }
    table#cart tfoot td .btn{display:block;}

}

 

Routes

At this point go to routes>web.php and add the following routes:

<?php

/*
|--------------------------------------------------------------------------
| 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('/', 'ProductsController@index');

Route::get('cart', 'ProductsController@cart');

Route::get('add-to-cart/{id}', 'ProductsController@addToCart');

Now visit http://localhost/shopping-cart/public/ and http://localhost/shopping-cart/public/cart you will see our products and cart page respectively.

 

Displaying Products

Go to ProductsController.php in the index function add the below code

public function index()
    {
        $products = Product::all();

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

Here we fetch all products and sent them to the products view.

Now go to resources>views>products.blade.php and replace the dummy data with the below code

@extends('layout')

@section('title', 'Products')

@section('content')

    <div class="container products">

        <div class="row">

            @foreach($products as $product)
                <div class="col-xs-18 col-sm-6 col-md-3">
                    <div class="thumbnail">
                        <img src="{{ $product->photo }}" width="500" height="300">
                        <div class="caption">
                            <h4>{{ $product->name }}</h4>
                            <p>{{ str_limit(strtolower($product->description), 50) }}</p>
                            <p><strong>Price: </strong> {{ $product->price }}$</p>
                            <p class="btn-holder"><a href="{{ url('add-to-cart/'.$product->id) }}" class="btn btn-warning btn-block text-center" role="button">Add to cart</a> </p>
                        </div>
                    </div>
                </div>
            @endforeach

        </div><!-- End row -->

    </div>

@endsection

Great work now you can see the actual products by going to http://localhost/shopping-cart/public/

Processing the cart

Now its time to add logic for when user clicks on add to cart button. We will do this in the addToCart function in ProductsController.php and we will store the cart item using laravel session.

public function addToCart($id)
    {
        $product = Product::find($id);

        if(!$product) {

            abort(404);

        }

        $cart = session()->get('cart');

        // if cart is empty then this the first product
        if(!$cart) {

            $cart = [
                    $id => [
                        "name" => $product->name,
                        "quantity" => 1,
                        "price" => $product->price,
                        "photo" => $product->photo
                    ]
            ];

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

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

        // if cart not empty then check if this product exist then increment quantity
        if(isset($cart[$id])) {

            $cart[$id]['quantity']++;

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

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

        }

        // if item not exist in cart then add to cart with quantity = 1
        $cart[$id] = [
            "name" => $product->name,
            "quantity" => 1,
            "price" => $product->price,
            "photo" => $product->photo
        ];

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

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

In the above code first we fetch the product and checked if it exist or not then we check if there is a cart exist in the session. If cart is empty then we treated the item as the first product and insert it along with quantity and price. If cart not empty we checked if the product already exist and increment its quantity.

 

Displaying the cart contents

At this point we have a cart with products let’s display it in the cart view.

Go to resources>views>cart.blade.php and update the view with below code:

@extends('layout')

@section('title', 'Cart')

@section('content')

    <table id="cart" class="table table-hover table-condensed">
        <thead>
        <tr>
            <th style="width:50%">Product</th>
            <th style="width:10%">Price</th>
            <th style="width:8%">Quantity</th>
            <th style="width:22%" class="text-center">Subtotal</th>
            <th style="width:10%"></th>
        </tr>
        </thead>
        <tbody>

        <?php $total = 0 ?>

        @if(session('cart'))
            @foreach(session('cart') as $id => $details)

                <?php $total += $details['price'] * $details['quantity'] ?>

                <tr>
                    <td data-th="Product">
                        <div class="row">
                            <div class="col-sm-3 hidden-xs"><img src="{{ $details['photo'] }}" width="100" height="100" class="img-responsive"/></div>
                            <div class="col-sm-9">
                                <h4 class="nomargin">{{ $details['name'] }}</h4>
                            </div>
                        </div>
                    </td>
                    <td data-th="Price">${{ $details['price'] }}</td>
                    <td data-th="Quantity">
                        <input type="number" value="{{ $details['quantity'] }}" class="form-control quantity" />
                    </td>
                    <td data-th="Subtotal" class="text-center">${{ $details['price'] * $details['quantity'] }}</td>
                    <td class="actions" data-th="">
                        <button class="btn btn-info btn-sm update-cart" data-id="{{ $id }}"><i class="fa fa-refresh"></i></button>
                        <button class="btn btn-danger btn-sm remove-from-cart" data-id="{{ $id }}"><i class="fa fa-trash-o"></i></button>
                    </td>
                </tr>
            @endforeach
        @endif

        </tbody>
        <tfoot>
        <tr class="visible-xs">
            <td class="text-center"><strong>Total {{ $total }}</strong></td>
        </tr>
        <tr>
            <td><a href="{{ url('/') }}" class="btn btn-warning"><i class="fa fa-angle-left"></i> Continue Shopping</a></td>
            <td colspan="2" class="hidden-xs"></td>
            <td class="hidden-xs text-center"><strong>Total ${{ $total }}</strong></td>
        </tr>
        </tfoot>
    </table>

@endsection

And also update the main layout view layout.blade.php

<!DOCTYPE html>
<html>
<head>

    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

    <title>@yield('title')</title>

    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css">
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css">
    <link rel="stylesheet" type="text/css" href="{{ asset('css/style.css') }}">

    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"></script>

</head>
<body>

<div class="container">

    <div class="row">
        <div class="col-lg-12 col-sm-12 col-12 main-section">
            <div class="dropdown">
                <button type="button" class="btn btn-info" data-toggle="dropdown">
                    <i class="fa fa-shopping-cart" aria-hidden="true"></i> Cart <span class="badge badge-pill badge-danger">{{ count((array) session('cart')) }}</span>
                </button>
                <div class="dropdown-menu">
                    <div class="row total-header-section">
                        <div class="col-lg-6 col-sm-6 col-6">
                            <i class="fa fa-shopping-cart" aria-hidden="true"></i> <span class="badge badge-pill badge-danger">{{ count((array) session('cart')) }}</span>
                        </div>

                        <?php $total = 0 ?>
                        @foreach((array) session('cart') as $id => $details)
                            <?php $total += $details['price'] * $details['quantity'] ?>
                        @endforeach

                        <div class="col-lg-6 col-sm-6 col-6 total-section text-right">
                            <p>Total: <span class="text-info">$ {{ $total }}</span></p>
                        </div>
                    </div>

                    @if(session('cart'))
                        @foreach(session('cart') as $id => $details)
                            <div class="row cart-detail">
                                <div class="col-lg-4 col-sm-4 col-4 cart-detail-img">
                                    <img src="{{ $details['photo'] }}" />
                                </div>
                                <div class="col-lg-8 col-sm-8 col-8 cart-detail-product">
                                    <p>{{ $details['name'] }}</p>
                                    <span class="price text-info"> ${{ $details['price'] }}</span> <span class="count"> Quantity:{{ $details['quantity'] }}</span>
                                </div>
                            </div>
                        @endforeach
                    @endif
                    <div class="row">
                        <div class="col-lg-12 col-sm-12 col-12 text-center checkout">
                            <a href="{{ url('cart') }}" class="btn btn-primary btn-block">View all</a>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>

<div class="container page">
    @yield('content')
</div>

@yield('scripts')

</body>
</html>

 

Updating & removing from the cart

Now to remove or update an item in the cart we will create two actions in the ProductsController as follows:

public function update(Request $request)
    {
        if($request->id and $request->quantity)
        {
            $cart = session()->get('cart');

            $cart[$request->id]["quantity"] = $request->quantity;

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

            session()->flash('success', 'Cart updated successfully');
        }
    }

    public function remove(Request $request)
    {
        if($request->id) {

            $cart = session()->get('cart');

            if(isset($cart[$request->id])) {

                unset($cart[$request->id]);

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

            session()->flash('success', 'Product removed successfully');
        }
    }

Let’s create two other routes

Route::patch('update-cart', 'ProductsController@update');

Route::delete('remove-from-cart', 'ProductsController@remove');

Now go to resources>views>cart.blade.php and add this code at the bottom

@section('scripts')


    <script type="text/javascript">

        $(".update-cart").click(function (e) {
           e.preventDefault();

           var ele = $(this);

            $.ajax({
               url: '{{ url('update-cart') }}',
               method: "patch",
               data: {_token: '{{ csrf_token() }}', id: ele.attr("data-id"), quantity: ele.parents("tr").find(".quantity").val()},
               success: function (response) {
                   window.location.reload();
               }
            });
        });

        $(".remove-from-cart").click(function (e) {
            e.preventDefault();

            var ele = $(this);

            if(confirm("Are you sure")) {
                $.ajax({
                    url: '{{ url('remove-from-cart') }}',
                    method: "DELETE",
                    data: {_token: '{{ csrf_token() }}', id: ele.attr("data-id")},
                    success: function (response) {
                        window.location.reload();
                    }
                });
            }
        });

    </script>

@endsection

As shown above we added two listeners for buttons update and remove and for each button just send ajax request to update and remove products.

Download the source

And this is an updated version of the tutorial that uses ajax

https://bitbucket.org/webmobtuts/shopping-cart-tutorial-laravel/src/master/

 

Conclusion

You learned in this tutorial how to build a shopping cart with laravel. I decided to built this from scratch although there are ready made packages in laravel for shopping carts but to let you understand the basics of shopping cart. You can also extend this tutorial to add functionality of checkout, payments, and more

4.3 46 votes
Article Rating

What's your reaction?

Excited
40
Happy
31
Not Sure
13
Confused
29

You may also like

Subscribe
Notify of
guest
128 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Elias
Elias
3 years ago

Obtive error: count(): Parameter must be an array or an object that implements Countable.
Código blade: {{ count(session(‘cart’)) }}

beryl
beryl
3 years ago
Reply to  WebMobTuts

i got this error i’m using xampp on windows
is there any solution to solve this?

Ruben
Ruben
3 years ago
Reply to  WebMobTuts

how to implement in 7.3 php version

Jesse
Jesse
3 years ago
Reply to  WebMobTuts

Thanks for the great tutorial, replace your layout.blade.php code with the following and it will fix your problem.
—————————————————————-

Change
{{ count(session(‘cart’)) }}
to
@if(session(‘cart’)!==null)
{{ count(session(‘cart’)) }}
@endif

Change
@foreach(session(‘cart’) as $id => $details)

@endforeach
to
@if(session(‘cart’)!==null)
@foreach(session(‘cart’) as $id => $details)

@endforeach
@endif

william ramirez
1 year ago
Reply to  WebMobTuts

Funciona yo lo probe en la version de Php 7.3.12 con laravel 7. Las dos Versiones de Código de arriba. Saludos. Gracias…

beryl
beryl
3 years ago
Reply to  Elias

i got it fixed, just add (array) before the session
{{ count(session(‘cart’)) }}
to
{{ count((array)session(‘cart’)) }}

Haseena
Haseena
2 years ago
Reply to  beryl

No use same error was displaying. like as below:

count(): Parameter must be an array or an object that implements Countable

luis
luis
3 years ago

hola me sale este error al momento de usar el comando “php artisan migrate”

In Parser.php line 120:
dotenv values containing spaces must be surrounded by quotes.

carlos Garcia
carlos Garcia
3 years ago

Hola, como puedo hacer que la primera pagina sea el welcome, luego de registrarse, iniciar sesion, aparezcan los productos ??? Gracias

bouzaffara nadim
bouzaffara nadim
3 years ago

hello ,I got Invalid argument supplied for foreach() ,any solution ?

moza
moza
3 years ago
Reply to  WebMobTuts

Hi brother I fixed session cart like you but error foreach. Could you help please

Sam
Sam
3 years ago

Great tutorial! Thank you.

priya
priya
3 years ago

Parse error: syntax error, unexpected ‘cart’ (T_STRING), expecting ‘,’ or ‘)’ (View: C:\xampp\htdocs\shopping-cart-demo\resources\views\layout.blade.php) (View: C:\xampp\htdocs\shopping-cart-demo\resources\views\layout.blade.php)

moza
moza
3 years ago

Dear all I find the solution it is good in view/layout.blade.php in foreach you sould pass is code is working good

@if (is_array(session(‘cart’)))
@foreach(session(‘cart’) as $id => $details)

@endforeach
@endif

juma
juma
3 years ago

This can’t delete cart or update , it’s just saying “are you sure” then nothing changes why?

manpreet
3 years ago
Reply to  WebMobTuts

Yes , same issue with me
Getting 500 error in console

Apri
Apri
2 years ago
Reply to  manpreet

you just wanna include script JQUERY in layout.blade.php in

nayeem
nayeem
3 years ago

violation access error 767 bytes in windows

nayeem
nayeem
3 years ago

Syntax error or access violation: 1071 Specified key was too long; max key length is 767 bytes

Ashutosh Rai
Ashutosh Rai
2 years ago

Class ‘App\Http\Controllers\Product’ not found

Ashutosh Rai
Ashutosh Rai
2 years ago

$products = Product::all(); in ProductsController
Class ‘App\Http\Controllers\Product’ not found

Apri
Apri
2 years ago

Hay dude… Sorry, can you help me?
My @yield(‘script’) from cart.blade.php can’t work after remove-from-cart and update-cart onclick in button.
My cart can’t update quantity and can’t remove product from cart. Please help me…
Thankyou dude…

ugo
ugo
2 years ago

Thanks alot. I appreciate every bit of ur code. More grace

Johnson
2 years ago

I would rather use existing package and app that is out there. I have use this one for one of my client.

https://github.com/avored/laravel-ecommerce

Matildah
Matildah
2 years ago

am getting the error
A non-numeric value encountered (View: C:\xampp\htdocs\Tafuta_restaurant\resources\views\restaurants\cart.blade.php)

Andrea
Andrea
2 years ago

Hi, first of all thanks, your tutorial helped me a lot but I have a problem, I do not understand how the variable “quantity” works since it is not defined in the database and my cart is not storing it.
Could you explain to me how the variable “quantity” works and how do you use it?

Thank you.

Andrea
Andrea
2 years ago
Reply to  WebMobTuts

thanks for answerme. I’m doing a chatbot, customers write the quantity of products they require. I capture in a variable “$quantity” what the customer writes (number): foreach ($product as $key => $value) { $cart = [ $p => [ “code” => $value->code, “quantity” => $quantity, “price” => $value->price, “archImg” => $value->archImg ] ]; session()->put(‘cart’, $cart); $this->say(‘success 1’, ‘Product added to cart successfully!’); } } Then, when I want to add more products of the same type and increase the quantity, I don’t allow it: if(isset($cart[$p])) { $cart[$p][‘quantity’] + $quantity; session()->put(‘cart’, $cart); $this->say(‘success 2, Product added to cart successfully!’); } and… Read more »

modied
modied
2 years ago

Thanks . That is great. however when I press add to cart the page was refreshing mean reload How can I make it without refreshing

modied
modied
2 years ago
Reply to  WebMobTuts

how to make that

modied
modied
2 years ago
Reply to  WebMobTuts

may I give the code then you modify it?

modied
modied
2 years ago
Reply to  WebMobTuts

this a hearf **/ id) }}”>Add to Cart
/**

the rout and controller have done

modied
modied
2 years ago
Reply to  WebMobTuts

you already make code ajax in cart page at remove and update button but you write success function as reload function that refresh whole page when you click are there others code or idea

modied
modied
2 years ago
Reply to  WebMobTuts

$(“.remove-from-cart”).click(function (e) {
e.preventDefault();

var ele = $(this);

if(confirm(“Are you sure”)) {
$.ajax({
url: ‘{{ url(‘admin/remove-from-cart’) }}’,
method: “DELETE”,
data: {_token: ‘{{ csrf_token() }}’, id: ele.attr(“data-id”)},
success: function (response) {
window.location.reload();
}
});
}

modied
modied
2 years ago
Reply to  WebMobTuts

How can I express my thank for you there is no way ….. big thanks for you and the god save you

Chokovel
Chokovel
2 years ago

Thank you so much for this tutorial. After adding to cart the product photo does not display, it also does not display on view cart, what do i do please?

Chokovel
Chokovel
2 years ago
Reply to  WebMobTuts

No, it’s all working good. but it only displays product name, price, quantity, total but does not display product photo.

Chokovel
Chokovel
2 years ago
Reply to  Chokovel

Am using image to call my product image instead of photo, so when i tried changing photo to image both in the blade and controller, i get the error “Undefined index: image”, but when i use photo i get no errors but photo does not display.

Bonface Mwaura
Bonface Mwaura
2 years ago

Great tutorial! I am having trouble getting the cart totals (to enter into my database). How do I go about it?

Ahmed Aiman
Ahmed Aiman
2 years ago

how can i save each of my cart orders to a table in DB which can be viewed later by the user.

Ahmed Aiman
Ahmed Aiman
2 years ago
Reply to  Ahmed Aiman

I am using the ajax version here

Ahmed Aiman
Ahmed Aiman
2 years ago
Reply to  WebMobTuts

public function storeCart(Request $request){
Cart::create($request->all());
return redirect()->route(‘/’);
}

– I created a function as above. When the ‘storeCart’ is triggered, product_id appears as NULL and the quantity is always 0.00 in the database

Ahmed Aiman
Ahmed Aiman
2 years ago
Reply to  WebMobTuts

class Product extends Model
{
protected $fillable = [ ‘name’, ‘description’, ‘price’];
/**
* Get the post that owns the comment.
*/
public function carts()
{
return $this->hasMany(‘Cart’);
}
}

-This is my Product Model

Ahmed Aiman
Ahmed Aiman
2 years ago
Reply to  WebMobTuts

class Cart extends Model
{
protected $fillable = [

‘quantity’,

];
/**
* Get the comments for the blog post.
*/
public function products(){
return $this->hasMany(‘App\Product’,’product_id’);
}
}

-This is my Cart Model

zammet
zammet
2 years ago

I can’t delete the first row of the cart

zammet
zammet
2 years ago
Reply to  WebMobTuts

I don’t know. I need help on that. When i add other items to the cart, i can delete them apart from the first item added. And also if i add an item twice, it does not increase it’s quantity, it only adds it a second time.

Anayeli
Anayeli
2 years ago

hi,when I change the names and data I get this error: Undefined index: image
I changed it to this:
$cart = [
$id => [
“descripcion” => $product->DESCRIPCION,
“cantidad” => 1,
“precio” => $product->PRECIO_COSTE,
“imagen” => $product->IMAGEN
]
];
and in the view just change the names to how I put them in the controller

Govind Sharma
Govind Sharma
2 years ago

unable to refresh or delete item from cart

kuro
kuro
2 years ago

Use of undefined constant product – assumed ‘product’ (this will throw an Error in a future version of PHP)

i have this error for my addToCart function, please help me

Nkesiga Clinton
Nkesiga Clinton
2 years ago

When I trigger add-to-cart button it shows url with product id but displays
Sorry, the page you are looking for could not be found.

Narendra
Narendra
2 years ago

thanks for this code

Fer
Fer
2 years ago

No sirven las funciones de actualizar o remover salu2.

AFFO
AFFO
2 years ago

great !!!!!! your code help me thank.
May God bless you

Karen
2 years ago

I had a problem when updating the product quantity with multiple product in cart. When I update the first product it has no problem, but when I update the other product, the product quantity update with the same number as the first product.

choi
choi
1 year ago
Reply to  Karen

same here.. only the first product will update.

hassan
hassan
2 years ago

How to resolve this
ErrorException (E_ERROR)
Undefined variable: products (View: C:\Users\DSA\shopping-cart\resources\views\products.blade.php)
Previous exceptions
Undefined variable: products (0)

Cirexx
Cirexx
1 year ago

Hi.

I have a problem with sessions in Laravel 7. They don’t persist across the code.
For example, if a have a method called addToCart and I create a session within it, no problem with that, I can access to the session data and show it in a view. But when I try to call the session in another method I have called index, then it gives me NULL. Also, when I try to show the session in another view, it’s not possible, it gives me NULL too.

Do you know what could be the problem?.

Thanks,
Ciro.

Zafer
Zafer
1 year ago

Hello thanks for the tutorial
Is there a demo link?

Zafer
Zafer
1 year ago
Reply to  WebMobTuts

Thank you

phptechie
1 year ago

This is an excellent post. This is really helpful and for my business websites.

Asga
Asga
1 year ago

Thanks for the tutorial! but when I logout then login back the item disappear.

joe emako
joe emako
1 year ago

hello sir thank you for the tutorial but I have a little mouse button my product is not displayed

rvinram
rvinram
1 year ago

it run smoothly .. thanks……

rouf
rouf
1 year ago

have github?

alif
alif
1 year ago

Hi i got this error Property [photo] does not exist on this collection instance. (View: C:\Laravel_Project\Project2\resources\views\products.blade.php), im using php 7.4.11

John Jhonny
John Jhonny
1 year ago

Illegal string offset ‘quantity’

priyanka deshmukh
priyanka deshmukh
1 year ago

 “message”: “The GET method is not supported for this route. Supported methods: PATCH.”,
when i am trying to update cart get this error on console.

mamad
mamad
1 year ago

amazing 😍😍😍😍

Ankit
1 year ago

delete method is not working

Last edited 1 year ago by Ankit
jim parker
jim parker
9 months ago

i like but can u share some tutorial about add to cart using cookie

Phương thanh
Phương thanh
8 months ago

file style.css tạo ở đâu hay nằm ở đâu ạ

Danish
Danish
8 months ago

what if i have single button for Add to Cart and a dropdownlist for products and now select a product and add to cart with a single button which is out of foreach loop.Now my gets last product id and add it in cart. Any suggestion for this

alipar
alipar
8 months ago

Is this secure? I mean you are saving price in session. Is user able to change session variables? If it is , how can we handle it?