If you’re new to Laravel or web development in general and trying to build practice projects, it’s highly likely that you’ll want to build an e-commerce store of some sort. Being someone who has worked on a number of e-commerce platforms, I can tell that one of the most complicated features of an e-commerce store for a first-timer is the Laravel shopping cart.
Although it sounds pretty simple on paper, once you start to implement the cart yourself, you’ll quickly realize that there are a lot of cases that you have to account for, and there are lots of ways to create a cart.
In this article, I’ll show the Laravel developers how you can create a session-based Laravel Livewire shopping cart. Keep in mind, that I’m assuming that you already know the basics of Laravel and Livewire. I also have a reference project repository for this article that you may look at.
Table of contents
The Database Setup
Before jumping into coding the cart, you’ll have to set up the necessary models and migrations. In this example, all you need is a Product
model and a migration for the products table. You can use artisan
to create the model and the migrations. The code for the model is as follows:
<?php
namespace App\Models;
use App\Contracts\Cartable;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Product extends Model
{
use HasFactory;
// you only live once
protected $guarded = [];
public function getUnitPriceAttribute($value)
{
return number_format($value, 2);
}
}
The code for the migration file is as follows:
<?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->text('description');
$table->float('unit_price', 8, 2, true);
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('products');
}
}
I also have factory for the products to start with some data on my database from the get go. The code for the factory as follows:
<?php
namespace Database\Factories;
use App\Models\Product;
use Illuminate\Database\Eloquent\Factories\Factory;
class ProductFactory extends Factory
{
/**
* The name of the factory's corresponding model.
*
* @var string
*/
protected $model = Product::class;
/**
* Define the model's default state.
*
* @return array
*/
public function definition()
{
return [
'name' => $this->faker->word(),
'description' => $this->faker->paragraph(2),
'unit_price' => $this->faker->randomFloat(2, 50, 5000),
];
}
}
The aforementioned reference project comes with all of these built-in so I would suggest you use that as your starting point.
The Cart Service
Again, if you’re a beginner you may think that the best place to write the cart logic is a controller may be called CartController but I have a better idea. You see if you put a set of logic within a controller that logic can only be invoked by dispatching a request to the corresponding endpoint. But with Livewire, you want to put the logic somewhere that can be accessed even outside of a request. In this article, we’ll not have any controller whatsoever. We’ll have some Livewire Laravel components and a service class.
The idea of service classes is not something built into the framework or documented in the official docs. As a result, different people refer to them differently. At the end of the day, service classes are plain classes responsible for holding the business logic.
Now where to keep these classes is totally up to you, but I prefer putting it within the app/Services
directory. I’m naming the file as CartService.php
and start by following lines of code there:
<?php
namespace App\Services;
use Illuminate\Support\Collection;
use Illuminate\Session\SessionManager;
class CartService {
const MINIMUM_QUANTITY = 1;
const DEFAULT_INSTANCE = 'shopping-cart';
protected $session;
protected $instance;
/**
* Constructs a new cart object.
*
* @param Illuminate\Session\SessionManager $session
*/
public function __construct(SessionManager $session)
{
$this->session = $session;
}
}
As you may have guessed, we’ll build this class step by step. There are two protected variables and two constants in this class. The MINIMUM_QUANTITY
is the minimum quantity of a product that has to exist in the cart. Assume someone has added multiple units of a product in the cart and then they want to discard some of those unit. The lowest they can go is the value of this constant.
The next constant is the DEFAULT_INSTANCE
which is simply the name of the cart object in the session. Finally, the $session
variable is going to be an instance of the Illuminate\Session\SessionManager
class and the $instance
is going to be a reference to the current instance of the cart.
If you don’t understand everything clearly at the moment don’t worry, you’ll soon understand all of it. There is also the class constructor that takes an instance of the Illuminate\Session\SessionManager
class and saves it into the $session
variable.
The next thing you want to do is create two protected methods. One named createCartItem
which will accept a bunch of information about a cart item and return a well formatted collection to store in the cart.
The second protected method will be, getContent
responsible for returning all the content of the cart as a collection. Update the code as follows:
<?php
namespace App\Services;
use Illuminate\Support\Collection;
use Illuminate\Session\SessionManager;
class CartService {
const MINIMUM_QUANTITY = 1;
const DEFAULT_INSTANCE = 'shopping-cart';
protected $session;
protected $instance;
/**
* Constructs a new cart object.
*
* @param Illuminate\Session\SessionManager $session
*/
public function __construct(SessionManager $session)
{
$this->session = $session;
}
/**
* Returns the content of the cart.
*
* @return Illuminate\Support\Collection
*/
protected function getContent(): Collection
{
return $this->session->has(self::DEFAULT_INSTANCE) ? $this->session->get(self::DEFAULT_INSTANCE) : collect([]);
}
/**
* Creates a new cart item from given inputs.
*
* @param string $name
* @param string $price
* @param string $quantity
* @param array $options
* @return Illuminate\Support\Collection
*/
protected function createCartItem(string $name, string $price, string $quantity, array $options): Collection
{
$price = floatval($price);
$quantity = intval($quantity);
if ($quantity < self::MINIMUM_QUANTITY) {
$quantity = self::MINIMUM_QUANTITY;
}
return collect([
'name' => $name,
'price' => $price,
'quantity' => $quantity,
'options' => $options,
]);
}
}
The getContent
function checks if the session has a cart object or not. If yes, returns the cart object and if not, returns an empty cart. Here, the cart object is an instance of the Illuminate\Support\Collection
class.
The createCartItem
method on the other hand, accepts the name, price, quantity and options of a given item and then returns them in the form of a collection. This returned object is what we consider a cart item. Considering the received values will be in string format, the price and quantity will have to be converted to float and integer respectively. We’ll talk about options later on.
Now that you have finished the two protected methods, it’s time to start writing the public methods. You’ll have six public methods, each performing a certain cart action and accessible from the Livewire Laravel components. Let’s begin with the add to cart functionality. Update the code as follows:
<?php
namespace App\Services;
use Illuminate\Support\Collection;
use Illuminate\Session\SessionManager;
class CartService {
const MINIMUM_QUANTITY = 1;
const DEFAULT_INSTANCE = 'shopping-cart';
protected $session;
protected $instance;
/**
* Constructs a new cart object.
*
* @param Illuminate\Session\SessionManager $session
*/
public function __construct(SessionManager $session)
{
$this->session = $session;
}
/**
* Adds a new item to the cart.
*
* @param string $id
* @param string $name
* @param string $price
* @param string $quantity
* @param array $options
* @return void
*/
public function add($id, $name, $price, $quantity, $options = []): void
{
$cartItem = $this->createCartItem($name, $price, $quantity, $options);
$content = $this->getContent();
if ($content->has($id)) {
$cartItem->put('quantity', $content->get($id)->get('quantity') + $quantity);
}
$content->put($id, $cartItem);
$this->session->put(self::DEFAULT_INSTANCE, $content);
}
/**
* Returns the content of the cart.
*
* @return Illuminate\Support\Collection
*/
protected function getContent(): Collection
{
return $this->session->has(self::DEFAULT_INSTANCE) ? $this->session->get(self::DEFAULT_INSTANCE) : collect([]);
}
/**
* Creates a new cart item from given inputs.
*
* @param string $name
* @param string $price
* @param string $quantity
* @param array $options
* @return Illuminate\Support\Collection
*/
protected function createCartItem(string $name, string $price, string $quantity, array $options): Collection
{
$price = floatval($price);
$quantity = intval($quantity);
if ($quantity < self::MINIMUM_QUANTITY) {
$quantity = self::MINIMUM_QUANTITY;
}
return collect([
'name' => $name,
'price' => $price,
'quantity' => $quantity,
'options' => $options,
]);
}
}
The add
method receives the id, name, price, quantity, options for a product from the user. The options is initialized as an empty array. Once the method has the information, it creates a new cart item by calling the createCartItem
protected method.
Then the method gets the cart content by calling the getContent
protected method and checks if the product already exists in the cart. If yes, the method updates the quantity of the car item in the cart and puts and updates the cart object. Otherwise the method just puts the cart item in the cart and moves on.
The next method you’ll be working on is the update
methods used for updating a cart item in the cart. This one’s going to be a bit more complicated than the add
method. Update your code as follows:
<?php
namespace App\Services;
use Illuminate\Support\Collection;
use Illuminate\Session\SessionManager;
class CartService {
const MINIMUM_QUANTITY = 1;
const DEFAULT_INSTANCE = 'shopping-cart';
protected $session;
protected $instance;
/**
* Constructs a new cart object.
*
* @param Illuminate\Session\SessionManager $session
*/
public function __construct(SessionManager $session)
{
$this->session = $session;
}
/**
* Adds a new item to the cart.
*
* @param string $id
* @param string $name
* @param string $price
* @param string $quantity
* @param array $options
* @return void
*/
public function add($id, $name, $price, $quantity, $options = []): void
{
$cartItem = $this->createCartItem($name, $price, $quantity, $options);
$content = $this->getContent();
if ($content->has($id)) {
$cartItem->put('quantity', $content->get($id)->get('quantity') + $quantity);
}
$content->put($id, $cartItem);
$this->session->put(self::DEFAULT_INSTANCE, $content);
}
/**
* Updates the quantity of a cart item.
*
* @param string $id
* @param string $action
* @return void
*/
public function update(string $id, string $action): void
{
$content = $this->getContent();
if ($content->has($id)) {
$cartItem = $content->get($id);
switch ($action) {
case 'plus':
$cartItem->put('quantity', $content->get($id)->get('quantity') + 1);
break;
case 'minus':
$updatedQuantity = $content->get($id)->get('quantity') - 1;
if ($updatedQuantity < self::MINIMUM_QUANTITY) {
$updatedQuantity = self::MINIMUM_QUANTITY;
}
$cartItem->put('quantity', $updatedQuantity);
break;
}
$content->put($id, $cartItem);
$this->session->put(self::DEFAULT_INSTANCE, $content);
}
}
/**
* Returns the content of the cart.
*
* @return Illuminate\Support\Collection
*/
protected function getContent(): Collection
{
return $this->session->has(self::DEFAULT_INSTANCE) ? $this->session->get(self::DEFAULT_INSTANCE) : collect([]);
}
/**
* Creates a new cart item from given inputs.
*
* @param string $name
* @param string $price
* @param string $quantity
* @param array $options
* @return Illuminate\Support\Collection
*/
protected function createCartItem(string $name, string $price, string $quantity, array $options): Collection
{
$price = floatval($price);
$quantity = intval($quantity);
if ($quantity < self::MINIMUM_QUANTITY) {
$quantity = self::MINIMUM_QUANTITY;
}
return collect([
'name' => $name,
'price' => $price,
'quantity' => $quantity,
'options' => $options,
]);
}
}
The update
method can wither increase or decrease the quantity of a cart item. All it needs to know is the id of the cart item and whether you want to increase or decrease its quantity. Once it has those information, the method retrieves the cart content, checks if the given item exists or not. If it exists, then based on the attempted action type, it either increases or decreases the item quantity.
The next two public methods are the remove
and the clear
methods responsible for removing a simple item from the cart and all items from the cart respectively. Update your code as follows:
<?php
namespace App\Services;
use Illuminate\Support\Collection;
use Illuminate\Session\SessionManager;
class CartService {
const MINIMUM_QUANTITY = 1;
const DEFAULT_INSTANCE = 'shopping-cart';
protected $session;
protected $instance;
/**
* Constructs a new cart object.
*
* @param Illuminate\Session\SessionManager $session
*/
public function __construct(SessionManager $session)
{
$this->session = $session;
}
/**
* Adds a new item to the cart.
*
* @param string $id
* @param string $name
* @param string $price
* @param string $quantity
* @param array $options
* @return void
*/
public function add($id, $name, $price, $quantity, $options = []): void
{
$cartItem = $this->createCartItem($name, $price, $quantity, $options);
$content = $this->getContent();
if ($content->has($id)) {
$cartItem->put('quantity', $content->get($id)->get('quantity') + $quantity);
}
$content->put($id, $cartItem);
$this->session->put(self::DEFAULT_INSTANCE, $content);
}
/**
* Updates the quantity of a cart item.
*
* @param string $id
* @param string $action
* @return void
*/
public function update(string $id, string $action): void
{
$content = $this->getContent();
if ($content->has($id)) {
$cartItem = $content->get($id);
switch ($action) {
case 'plus':
$cartItem->put('quantity', $content->get($id)->get('quantity') + 1);
break;
case 'minus':
$updatedQuantity = $content->get($id)->get('quantity') - 1;
if ($updatedQuantity < self::MINIMUM_QUANTITY) {
$updatedQuantity = self::MINIMUM_QUANTITY;
}
$cartItem->put('quantity', $updatedQuantity);
break;
}
$content->put($id, $cartItem);
$this->session->put(self::DEFAULT_INSTANCE, $content);
}
}
/**
* Removes an item from the cart.
*
* @param string $id
* @return void
*/
public function remove(string $id): void
{
$content = $this->getContent();
if ($content->has($id)) {
$this->session->put(self::DEFAULT_INSTANCE, $content->except($id));
}
}
/**
* Clears the cart.
*
* @return void
*/
public function clear(): void
{
$this->session->forget(self::DEFAULT_INSTANCE);
}
/**
* Returns the content of the cart.
*
* @return Illuminate\Support\Collection
*/
protected function getContent(): Collection
{
return $this->session->has(self::DEFAULT_INSTANCE) ? $this->session->get(self::DEFAULT_INSTANCE) : collect([]);
}
/**
* Creates a new cart item from given inputs.
*
* @param string $name
* @param string $price
* @param string $quantity
* @param array $options
* @return Illuminate\Support\Collection
*/
protected function createCartItem(string $name, string $price, string $quantity, array $options): Collection
{
$price = floatval($price);
$quantity = intval($quantity);
if ($quantity < self::MINIMUM_QUANTITY) {
$quantity = self::MINIMUM_QUANTITY;
}
return collect([
'name' => $name,
'price' => $price,
'quantity' => $quantity,
'options' => $options,
]);
}
}
The remove
method takes a cart item id and removes it from the cart collection and the clear
method simply drops the cart collection from the session completely. Finally there are two more public methods left. They are the total
and content
methods responsible for returning the cart total and the content of the cart to the front end. Update your code as follows:
<?php
namespace App\Services;
use Illuminate\Support\Collection;
use Illuminate\Session\SessionManager;
class CartService {
const MINIMUM_QUANTITY = 1;
const DEFAULT_INSTANCE = 'shopping-cart';
protected $session;
protected $instance;
/**
* Constructs a new cart object.
*
* @param Illuminate\Session\SessionManager $session
*/
public function __construct(SessionManager $session)
{
$this->session = $session;
}
/**
* Adds a new item to the cart.
*
* @param string $id
* @param string $name
* @param string $price
* @param string $quantity
* @param array $options
* @return void
*/
public function add($id, $name, $price, $quantity, $options = []): void
{
$cartItem = $this->createCartItem($name, $price, $quantity, $options);
$content = $this->getContent();
if ($content->has($id)) {
$cartItem->put('quantity', $content->get($id)->get('quantity') + $quantity);
}
$content->put($id, $cartItem);
$this->session->put(self::DEFAULT_INSTANCE, $content);
}
/**
* Updates the quantity of a cart item.
*
* @param string $id
* @param string $action
* @return void
*/
public function update(string $id, string $action): void
{
$content = $this->getContent();
if ($content->has($id)) {
$cartItem = $content->get($id);
switch ($action) {
case 'plus':
$cartItem->put('quantity', $content->get($id)->get('quantity') + 1);
break;
case 'minus':
$updatedQuantity = $content->get($id)->get('quantity') - 1;
if ($updatedQuantity < self::MINIMUM_QUANTITY) {
$updatedQuantity = self::MINIMUM_QUANTITY;
}
$cartItem->put('quantity', $updatedQuantity);
break;
}
$content->put($id, $cartItem);
$this->session->put(self::DEFAULT_INSTANCE, $content);
}
}
/**
* Removes an item from the cart.
*
* @param string $id
* @return void
*/
public function remove(string $id): void
{
$content = $this->getContent();
if ($content->has($id)) {
$this->session->put(self::DEFAULT_INSTANCE, $content->except($id));
}
}
/**
* Clears the cart.
*
* @return void
*/
public function clear(): void
{
$this->session->forget(self::DEFAULT_INSTANCE);
}
/**
* Returns the content of the cart.
*
* @return Illuminate\Support\Collection
*/
public function content(): Collection
{
return is_null($this->session->get(self::DEFAULT_INSTANCE)) ? collect([]) : $this->session->get(self::DEFAULT_INSTANCE);
}
/**
* Returns total price of the items in the cart.
*
* @return string
*/
public function total(): string
{
$content = $this->getContent();
$total = $content->reduce(function ($total, $item) {
return $total += $item->get('price') * $item->get('quantity');
});
return number_format($total, 2);
}
/**
* Returns the content of the cart.
*
* @return Illuminate\Support\Collection
*/
protected function getContent(): Collection
{
return $this->session->has(self::DEFAULT_INSTANCE) ? $this->session->get(self::DEFAULT_INSTANCE) : collect([]);
}
/**
* Creates a new cart item from given inputs.
*
* @param string $name
* @param string $price
* @param string $quantity
* @param array $options
* @return Illuminate\Support\Collection
*/
protected function createCartItem(string $name, string $price, string $quantity, array $options): Collection
{
$price = floatval($price);
$quantity = intval($quantity);
if ($quantity < self::MINIMUM_QUANTITY) {
$quantity = self::MINIMUM_QUANTITY;
}
return collect([
'name' => $name,
'price' => $price,
'quantity' => $quantity,
'options' => $options,
]);
}
}
The content
method checks if a cart collection exists and returns an empty collection if it doesn’t. The total
method sums up the total cost of the cart and returns it rounded off to two decimal points. That’s pretty much it, this is the final service class. Next is creating the Livewire components.
The Livewire Components
Again, I’m assuming that you know the basics of Laravel and Livewire so I’ll not walk you through step by step on how to create Livewire components and so on. I’ve made two Laravel Livewire examples. The first one is the product component that represents a single product shown to the user and the cart component responsible for showing the state of the cart.
On the left, each box showing a product information is a product component and on the right side, the entire cart view uses the cart component. The code for the app/Http/Livewire/ProductComponent.php
file is as follows:
<?php
namespace App\Http\Livewire;
use App\Facades\Cart;
use Livewire\Component;
use Illuminate\Contracts\View\View;
class ProductComponent extends Component
{
public $product;
public $quantity;
/**
* Mounts the component on the template.
*
* @return void
*/
public function mount(): void
{
$this->quantity = 1;
}
/**
* Renders the component on the browser.
*
* @return \Illuminate\Contracts\View\View
*/
public function render(): View
{
return view('livewire.product');
}
/**
* Adds an item to cart.
*
* @return void
*/
public function addToCart(): void
{
Cart::add($this->product->id, $this->product->name, $this->product->getRawOriginal('unit_price'), $this->quantity);
$this->emit('productAddedToCart');
}
}
A very straight forward component that takes the product and the quantity of the product as public properties. The product here is a product retrieved from the database. There is an addToCart
method that’ll be invoked by the Add To Cart buttons from the front end.
This method also emits an event called productAddedToCart
so that the cart component can be updated whenever a new product is added. Finally setting the quantity to 1 in the mount
method sets the default quantity to 1 in the front end.
The code for the resources/views/liveiwire/product.blade.php
which serves as the template for this component is as follows:
<div class="p-5 mx-2 my-2 max-w-md rounded border-2">
<h1 class="text-3xl mb-2">{{ $product->name }} - ${{ $product->unit_price }}</h1>
<p class="text-lg mb-2">{{ $product->description }}</p>
<input class="mb-2 border-2 rounded" type="number" min="1" wire:model="quantity">
<button class="p-2 border-2 rounded border-blue-500 hover:border-blue-600 bg-blue-500 hover:bg-blue-600" wire:click="addToCart">Add To Cart</button>
</div>
This component will later be used in another template file. Now the code for the app/Http/Livewire/CartComponent.php
is as follows:
<?php
namespace App\Http\Livewire;
use App\Facades\Cart;
use Livewire\Component;
use Illuminate\Contracts\View\View;
class CartComponent extends Component
{
protected $total;
protected $content;
protected $listeners = [
'productAddedToCart' => 'updateCart',
];
/**
* Mounts the component on the template.
*
* @return void
*/
public function mount(): void
{
$this->updateCart();
}
/**
* Renders the component on the browser.
*
* @return \Illuminate\Contracts\View\View
*/
public function render(): View
{
return view('livewire.cart', [
'total' => $this->total,
'content' => $this->content,
]);
}
/**
* Removes a cart item by id.
*
* @param string $id
* @return void
*/
public function removeFromCart(string $id): void
{
Cart::remove($id);
$this->updateCart();
}
/**
* Clears the cart content.
*
* @return void
*/
public function clearCart(): void
{
Cart::clear();
$this->updateCart();
}
/**
* Updates a cart item.
*
* @param string $id
* @param string $action
* @return void
*/
public function updateCartItem(string $id, string $action): void
{
Cart::update($id, $action);
$this->updateCart();
}
/**
* Rerenders the cart items and total price on the browser.
*
* @return void
*/
public function updateCart()
{
$this->total = Cart::total();
$this->content = Cart::content();
}
}
This component has methods for calling the update, remove and clear methods from the cart service. These methods will be invoked by buttons from the front end. It has the total cost of the cart, the content of the cart as protected properties and it listens to the productAddedToCart
event. Whenever this event is fired, the updateCart
method will be called and the total cost of cart along with the cart content will be updated.
The code for the resources/views/liveiwire/cart.blade.php
which serves as the template for this component is as follows:
<div class="w-1/4">
<div class="p-5 mx-2 my-2 max-w-md rounded border-2">
@if ($content->count() > 0)
@foreach ($content as $id => $item)
<p class="text-2xl text-right mb-2">
<button class="text-sm p-2 border-2 rounded border-gray-200 hover:border-gray-300 bg-gray-200 hover:bg-gray-300" wire:click="updateCartItem({{ $id }}, 'minus')"> - </button>
{{ $item->get('name') }} x {{ $item->get('quantity') }}
<button class="text-sm p-2 border-2 rounded border-gray-200 hover:border-gray-300 bg-gray-200 hover:bg-gray-300" wire:click="updateCartItem({{ $id }}, 'plus')"> + </button>
<button class="text-sm p-2 border-2 rounded border-red-500 hover:border-red-600 bg-red-500 hover:bg-red-600" wire:click="removeFromCart({{ $id }})">Remove</button>
</p>
@endforeach
<hr class="my-2">
<p class="text-xl text-right mb-2">Total: ${{ $total }}</p>
<button class="w-full p-2 border-2 rounded border-red-500 hover:border-red-600 bg-red-500 hover:bg-red-600" wire:click="clearCart">Clear Cart</button>
@else
<p class="text-3xl text-center mb-2">cart is empty!</p>
@endif
</div>
</div>
Finally these two components are used in the resources/views/index.blade.php
file as follows:
<x-guest-layout>
<div class="flex">
<div class="my-5 flex justify-center w-3/4"><h1 class="underline text-5xl">Products</h1></div>
<div class="my-5 flex justify-center w-1/4"><h1 class="underline text-5xl">Cart</h1></div>
</div>
<div class="flex">
<div class="flex flex-wrap justify-between w-3/4">
@foreach ($products as $product)
<livewire:product-component :product='$product' />
@endforeach
</div>
<livewire:cart-component />
</div>
</x-guest-layout>
This uses the resources/views/layouts/guest.blade.php
as the layout and its code is as follows:
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="csrf-token" content="{{ csrf_token() }}">
<title>{{ config('app.name', 'Laravel') }}</title>
<!-- Fonts -->
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Nunito:wght@400;600;700&display=swap">
<!-- Styles -->
<link rel="stylesheet" href="{{ asset('css/app.css') }}">
@livewireStyles
<!-- Scripts -->
<script src="{{ asset('js/app.js') }}" defer></script>
</head>
<body>
<nav class="p-5 flex justify-between shadow">
<a class="rounded text-3xl" href="{{ route('index') }}">Shopping Cart</a>
<div>
<a class="p-2 border-2 rounded bg-gray-200 hover:bg-gray-300" href="https://github.com/fhsinchy/laravel-livewire-shopping-cart" target="_blank" rel="noopener noreferrer">fhsinchy/laravel-livewire-shopping-cart</a>
</div>
</nav>
<div class="font-sans text-gray-900 antialiased">
{{ $slot }}
</div>
@livewireScripts
</body>
</html>
That’s all. If you want to run the reference project execute the following set of commands:
git clone https://github.com/fhsinchy/laravel-livewire-shopping-cart.git
cd laravel-livewire-shopping-cart
cp .env.example .env
touch database/database.sqlite
composer install
php artisan key:generate
php artisan migrate --seed
php artisan serve
Now visit http://localhost:8000 and you’ll see the application running.
Conclusion
I would like to thank you for the time you’ve spent reading this quick tutorial. I know this is not the definitive way of implementing a cart system and based on your necessities, it can be so so much more complex. But once you’ve got the basic idea, you should be able to extend from there and get to the Laravel Livewire testing of your shopping cart in no time. If you’re stuck somewhere, feel free to reach out on LinkedIn or Twitter.
If you want to read more related content on Laravel, check out the following articles: