Shopping Cart with Session and Eloquent ORM in Laravel

Create new database named laravel_db. In this database, create new table named product as below:

  1. Download and install the latest version of Composer from https://getcomposer.org/download/

  2. Open Windows Terminal in Visual Studio Code install Laravel Installer with command as below:

    composer global require laravel/installer
  3. Create new folder named LearnLaravelWithRealApps. Use Visual Studio Code open to LearnLaravelWithRealApps foler. In this folder, create new project named LearnLaravelWithRealApps with command as below:

    laravel new LearnLaravelWithRealApps

  4. Run LearnLaravelWithRealApps project with command as below:

    php artisan serve
  5. Open LearnLaravelWithRealApps project with url as below:

    http://localhost:8000

Open .env file in root folder. Add values as below connect to database:

DB_CONNECTION=mysql
DB_HOST=localhost
DB_PORT=3306
DB_DATABASE=laravel_db
DB_USERNAME=root
DB_PASSWORD=

Open Windows Terminal in Visual Studio Code and clear config cache with command as below:

php artisan config:clear

Create new PHP file named Product.php in app/Models folder as below:

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Product extends Model
{
    protected $primarykey = 'id';
    protected $table = 'product';
    public $timestamps = false;
}

Create new folder named Repositories. In Repositories folder, create new folder named Product. Create new PHP file named ProductRepository.php in app/Repositories/Product folder as below:

<?php

namespace App\Repositories\Product;

interface ProductRepository
{
    public function findAll();

    public function find($id);
}

Create new PHP file named ProductRepositoryImpl.php in app/Repositories/Product folder as below:

<?php

namespace App\Repositories\Product;

use App\Models\Product;

class ProductRepositoryImpl implements ProductRepository
{
    public function findAll()
    {
        return Product::get();
    }

    public function find($id)
    {
        return Product::find($id);
    }
}

Open AppServiceProvider.php file in app/Providers folder and add declare new repository to register method as below:

<?php

namespace App\Providers;

use App\Repositories\Product\ProductRepository;
use App\Repositories\Product\ProductRepositoryImpl;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    public function register()
    {
        $this->app->bind(ProductRepository::class, ProductRepositoryImpl::class);
    }

    public function boot()
    {
    }
}

In app/Http/Controllers folder, create new controllers as below:

Create new PHP file named ProductController.php as below:

<?php

namespace App\Http\Controllers;

use App\Repositories\Product\ProductRepository;

class ProductController extends Controller
{
    protected $productRepository;

    public function __construct(ProductRepository $productRepository)
    {
        $this->productRepository = $productRepository;
    }

    public function index()
    {
        $data = [
            'products' => $this->productRepository->findAll()
        ];
        return view('product/index')->with($data);
    }
}

Create new PHP file named CartController.php as below:

<?php

namespace App\Http\Controllers;

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

class CartController extends Controller
{
    protected $productRepository;

    public function __construct(ProductRepository $productRepository)
    {
        $this->productRepository = $productRepository;
    }

    public function index(Request $request)
    {
        $data = [
            'cart' => $request->session()->get('cart')
        ];
        return view('cart/index')->with($data);
    }

    public function buy($id, Request $request)
    {
        if (!$request->session()->has('cart')) {
            $cart = array();
            array_push($cart, [
                'product' => $this->productRepository->find($id),
                'quantity' => 1
            ]);
            $request->session()->put('cart', $cart);
        } else {
            $cart = $request->session()->get('cart');
            $index = $this->exists($id, $cart);
            if ($index == -1) {
                array_push($cart, [
                    'product' => $this->productRepository->find($id),
                    'quantity' => 1
                ]);
            } else {
                $cart[$index]['quantity']++;
            }
            $request->session()->put('cart', $cart);
        }
        return redirect('cart');
    }

    public function remove($id, Request $request)
    {
        $cart = $request->session()->get('cart');
        $index = $this->exists($id, $cart);
        unset($cart[$index]);
        $request->session()->put('cart', array_values($cart));
        return redirect('cart');
    }

    public function update(Request $request)
    {
        $quantities = $request->input('quantity');
        $cart = $request->session()->get('cart');
        for ($i = 0; $i < count($cart); $i++) {
            $cart[$i]['quantity'] = $quantities[$i];
        }
        $request->session()->put('cart', $cart);
        return redirect('cart');
    }

    private function exists($id, $cart)
    {
        for ($i = 0; $i < count($cart); $i++) {
            if ($cart[$i]['product']->id == $id) {
                return $i;
            }
        }
        return -1;
    }
}

In resources/views folder, create new views as below:

Create new folder named product in resources/views folder. In this folder, create new Blade file named index.blade.php as below:

<html>

    <head>
        <title>Laravel</title>
    </head>

    <body>

        <h3>Index</h3>
        <table border="1">
            <tr>
                <th>Id</th>
                <th>Name</th>
                <th>Price</th>
                <th>Quantity</th>
                <th>Status</th>
                <th>Created</th>
                <th>Description</th>
                <th>Action</th>
            </tr>
            @foreach($products as $product)
            <tr>
                <td>{{$product->id}}</td>
                <td>{{$product->name}}</td>
                <td>{{$product->price}}</td>
                <td>{{$product->quantity}}</td>
                <td>{{$product->status}}</td>
                <td>{{$product->created}}</td>
                <td>{{$product->description}}</td>
                <td>
                    <a href="{{url('/cart/buy/'.$product->id)}}">Buy Now</a>
                </td>
            </tr>
            @endforeach
        </table>

    </body>

</html>

Create new folder named cart in resources/views folder. In this folder, create new Blade file named index.blade.php as below:

<html>

    <head>
        <title>Laravel</title>
    </head>

    <body>

        <a href="{{url('/product')}}">Continue Shopping</a>
        <h3>Cart</h3>
        <form method="post" action="{{url('/cart/update')}}">
            @csrf
            <table border="1">
                <tr>
                    <th>Action</th>
                    <th>Id</th>
                    <th>Name</th>
                    <th>Price</th>
                    <th>Quantity <input type="submit" value="Update"></th>
                    <th>Total</th>
                </tr>
                @php $total = 0; @endphp
                @foreach($cart as $item)
                @php $total += $item['product']->price * $item['quantity']; @endphp
                <tr>
                    <td align="center"><a href="{{url('/cart/remove/'.$item['product']->id)}}">X</a></td>
                    <td>{{$item['product']->id}}</td>
                    <td>{{$item['product']->name}}</td>
                    <td>{{$item['product']->price}}</td>
                    <td>
                        <input type="number" min="1" value="{{$item['quantity']}}" name="quantity[]" style="width: 70px">
                    </td>
                    <td>{{$item['product']->price * $item['quantity']}}</td>
                </tr>
                @endforeach
                <tr>
                    <td colspan="5" align="right">Total</td>
                    <td>{{$total}}</td>
                </tr>
            </table>
        </form>

    </body>

</html>

Open web.php file in routes folder, add new routes as below:

<?php
    
use App\Http\Controllers\CartController;
use Illuminate\Support\Facades\Route;

use App\Http\Controllers\ProductController;

Route::group(['prefix' => 'product'], function () {
    Route::get('/', [ProductController::class, 'index']);
    Route::get('/index', [ProductController::class, 'index']);
});

Route::group(['prefix' => 'cart'], function () {
    Route::get('/', [CartController::class, 'index']);
    Route::get('/index', [CartController::class, 'index']);
    Route::get('/buy/{id}', [CartController::class, 'buy']);
    Route::get('/remove/{id}', [CartController::class, 'remove']);
    Route::post('/update', [CartController::class, 'update']);
});

Access index action in Demo controller with following url: http://localhost:8000/product/index

Output

Click Buy Now link to select product add to cart

Output