Pero lo más importante, aprenderás a crear un carrito de compras en Laravel haciendo uso del paquete darryldecode, el cual permite agregar productos a la canasta de una forma muy sencilla, pero además estos productos podrán ser guardados en cada usuario, si inicias sesión tendrás derecho a tener un carrito para cada usuario, iniciemos.
Lo primero que necesitamos es un proyecto de laravel, así que nos vamos a la carpeta que más te guste y ejecutamos el comando:
Laravel new carrito
Abrimos una terminal y entramos en la carpeta, Cd, Carrito "+ enter"
Nos creamos una base de datos, abrimos nuestro navegador favorito y escribimos en la barra de direcciones localhost/phpmyadmin - Bases de datos - carrito y damos clic en crear
Instalamos el paquete Laravel Breeze, el cual nos permite tener un registro de usuario y Login.
composer require laravel/breeze --dev
php artisan breeze:install
php artisan migrate
npm install
npm run dev
composer require "darryldecode/cart"
Darryldecode\Cart\CartServiceProvider::class,
'Cart' => Darryldecode\Cart\Facades\CartFacade::class,
php artisan make:model Product -m
$table->string('name')->unique();
$table->string('slug')->unique();
$table->string('details')->nullable();
$table->text('description')->nullable();
$table->double('price');
$table->double('precio_venta');
$table->double('shipping_cost')->nullable();
$table->string('sku')->nullable();
$table->integer('stock')->nullable();
$table->integer('category_id');
$table->unsignedInteger('brand_id')->unsigned();
$table->string('image_path');
php artisan make:seed ProductsTableSeeder
Y llenamos con los siguientes datosuse App\Models\Product;
public function run(): void
{
Product::create([
'name' => 'Producto Uno',
'slug' => 'producto-uno',
'details' =>'Este es un producto de prueba numero uno',
'description' => 'Esta es una descripcion del producto',
'price' => 250.00,
'precio_venta' => 450.00,
'shipping_cost' => 100.00,
'sku' => 'PLA-ROJ-323',
'stock' => 5,
'category_id' => 2,
'brand_id' => 5,
'image_path' => 'Imagen-1.jpg'
]);
Product::create([
'name' => 'Producto dos',
'slug' => 'producto-dos',
'details' =>'Este es un producto de prueba numero dos',
'description' => 'Esta es una descripcion del producto numero 2',
'price' => 250.00,
'precio_venta' => 450.00,
'shipping_cost' => 100.00,
'sku' => 'PLA-AZU-543',
'stock' => 5,
'category_id' => 2,
'brand_id' => 5,
'image_path'=> 'Imagen-2.jpg'
]);
Product::create([
'name' => 'Producto tres',
'slug' => 'producto-tres',
'details' =>'Este es un producto de prueba numero tres',
'description' => 'Esta es una descripcion del producto',
'price' => 250.00,
'precio_venta' => 450.00,
'shipping_cost' => 100.00,
'sku' => 'PLA-ROJ-323',
'stock' => 5,
'category_id' => 2,
'brand_id' => 5,
'image_path'=>'Imagen-3.jpg',
]);
Product::create([
'name' => 'Producto cuatro',
'slug' => 'producto-cuatro',
'details' =>'Este es un producto de prueba numero cuatro',
'description' => 'Esta es una descripcion del producto',
'price' => 250.00,
'precio_venta' => 450.00,
'shipping_cost' => 100.00,
'sku' => 'PLA-ROJ-323',
'stock' => 5,
'category_id' => 2,
'brand_id' => 5,
'image_path'=>'Imagen-4.jpg',
]);
Product::create([
'name' => 'Producto cinco',
'slug' => 'producto-cinco',
'details' =>'Este es un producto de prueba numero cinco',
'description' => 'Esta es una descripcion del producto',
'price' => 250.00,
'precio_venta' => 450.00,
'shipping_cost' => 100.00,
'sku' => 'PLA-ROJ-323',
'stock' => 5,
'category_id' => 2,
'brand_id' => 5,
'image_path'=>'Imagen-5.jpg'
]);
Product::create([
'name' => 'Producto seis',
'slug' => 'producto-seis',
'details' =>'Este es un producto de prueba numero seis',
'description' => 'Esta es una descripcion del producto',
'price' => 250.00,
'precio_venta' => 450.00,
'shipping_cost' => 100.00,
'sku' => 'PLA-ROJ-323',
'stock' => 5,
'category_id' => 2,
'brand_id' => 5,
'image_path'=>'Imagen-6.jpg'
]);
Product::create([
'name' => 'Producto siete',
'slug' => 'producto-siete',
'details' =>'Este es un producto de prueba numero siete',
'description' => 'Esta es una descripcion del producto',
'price' => 250.00,
'precio_venta' => 450.00,
'shipping_cost' => 100.00,
'sku' => 'PLA-ROJ-323',
'stock' => 5,
'category_id' => 2,
'brand_id' => 5,
'image_path'=>'Imagen-7.jpg',
]);
}
$this->call(ProductsTableSeeder::class);
Php artisan migrate
Php artisan db:seed
Php artisan storage:link
use App\Http\Controllers\Web\CartController;
Route::get('/', [CartController::class,'index'])->name('index');
Route::get('/cart', [CartController::class, 'cart'])->name('cart.index');
Route::post('/add', [CartController::class, 'add'])->name('cart.store');
Route::post('/update', [CartController::class, 'update'])->name('cart.update');
Route::post('/remove', [CartController::class, 'remove'])->name('cart.remove');
Route::post('/clear', [CartController::class, 'clear'])->name('cart.clear');
php artisan make:controller Web/CartController
use Illuminate\Support\Facades\Auth; use App\Models\Product;
public function __construct()
{
$this->middleware(['auth'])->except(['index']);
}
public function index(){
$userId = Auth::user();
$products = Product::all();
return view('Web.Tienda.index',compact('products','userId'));
}
public function cart() {
$userId = Auth::user();
$cartCollection = \Cart::session($userId)->getContent();
return view('Web.Carrito.index',compact('userId','cartCollection'));
}
public function remove(Request $request){
$userId = Auth::user();
\Cart::session($userId)->remove($request->id);
return redirect()->route('cart.index')->with('success_msg', 'El articulo ha sido borrado!');
}
public function add(Request$request){
$userId = Auth::user();
\Cart::session($userId)->add(array(
'id' => $request->id,
'name' => $request->name,
'price' => $request->price,
'quantity' => $request->quantity,
'attributes' => array(
'image' => $request->img,
'slug' => $request->slug
)
));
return redirect()->route('cart.index')->with('success_msg', 'El articulo ha sido agregado a su carrito!');
}
public function update(Request $request){
$userId = Auth::user();
\Cart::session($userId)->update($request->id,
array(
'quantity' => array(
'relative' => false,
'value' => $request->quantity
),
));
return redirect()->route('cart.index')->with('success_msg', 'Se ha actualizado el carrito!');
}
public function clear(){
$userId = Auth::user();
\Cart::session($userId)->clear();
return redirect()->route('cart.index')->with('success_msg', 'El carrito ha sido borrado con exito!');
}
Web
Partials
header.blade.php
footer.blade.php
css.blade.php
js.blade.php
Carrito
index.blade.php
Tienda
index.blade.php
Nos vamos al welcome.blade.php y agregamos las siguientes lineas
<head>
@include('Web.partials.css')
@stack('estilos')
</head>
<body>
@include('Web.partials.header')
@yield('contenido')
@include('Web.partials.footer')
@include('Web.partials.js')
@stack('scripts')
</body>
header.blade.php
<nav class="navbar navbar-expand-lg p-3 bg-light" id="headerNav">
<div class="container-fluid">
<button class="navbar-toggler"
type="button"
data-bs-toggle="collapse"
data-bs-target="#navbarNavDropdown"
aria-controls="navbarNavDropdown"
aria-expanded="false"
aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class=" collapse navbar-collapse " id="navbarNavDropdown">
<ul class="navbar-nav mx-auto ">
<li class="nav-item">
<a class="nav-link mx-2 " href="{{route('index')}}">Tienda</a>
</li>
<li class="nav-item bg-primary rounded">
<a class="nav-link mx-2 text-white" href="{{route('cart.index')}}">Carrito
<i class="fa-regular fa-cart-shopping"></i>
@if(Auth::check())
{{ \Cart::session($userId)->getTotalQuantity()}}
@endif
</a>
</li>
</ul>
</div>
</div>
</nav>
footer.blade.php
Este es el footer.
css.blade.php
<link rel="stylesheet" href="{{URL::asset('FrontEnd/css/bootstrap.min.css')}}">
<link rel="stylesheet" href="{{URL::asset('FrontEnd/css/mdb.min.css')}}">
<link rel="stylesheet" href="{{URL::asset('FrontEnd/css/fontawesome.min.css')}}">
<link rel="stylesheet" href="{{URL::asset('FrontEnd/css/solid.min.css')}}">
<link rel="stylesheet" href="{{URL::asset('FrontEnd/css/estilos.css')}}">
<script src="{{URL::asset('FrontEnd/js/bootstrap.bundle.min.js')}}"></script>
Carrito
index.blade.php
@extends('welcome')
@section('titulo', 'Obed Sánchez | Tienda')
@section ('imagen' , ('storage/img/uploads/blog-tecnologia-informatica-redes.jpg'))
@section('url' , '')
@section('estracto' , 'Bienvenido a mi blog oficial, sitio dedicado a la tienda')
@section('contenido')
<div class="container my-5 py-3 z-depth-1 rounded" >
<div class="row" id="carrito">
<div class="col-lg-12">
<section class="dark-grey-text">
<div class="table-responsive">
<table class="table product-table mb-0">
<thead class="mdb-color lighten-5">
<tr>
<th></th>
<th class="font-weight-bold">
<strong>Producto</strong>
</th>
<th></th>
<th class="font-weight-bold">
<strong>Precio</strong>
</th>
<th class="font-weight-bold">
<strong>Cantidad</strong>
</th>
</tr>
</thead>
<tbody>
@if(session()->has('success_msg'))
<div class="alert alert-success alert-dismissible fade show" role="alert">
{{ session()->get('success_msg') }}
</div>
@endif
@if(session()->has('alert_msg'))
<div class="alert alert-warning alert-dismissible fade show" role="alert">
{{ session()->get('alert_msg') }}
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
@endif
@if(count($errors) > 0)
@foreach($errors0>all() as $error)
<div class="alert alert-success alert-dismissible fade show" role="alert">
{{ $error }}
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
@endforeach
@endif
@if(\Cart::getTotalQuantity()>0)
<h4>{{ \Cart::getTotalQuantity()}} Producto(s) en el carrito</h4><br>
@else
<div class="text-center">
<h4>No Product(s) In Your Cart</h4><br>
<a href="/" class="btn btn-dark btn-rounded">ir a la tienda</a>
</div>
@endif
@foreach($cartCollection as $item)
<tr class="">
<th scope="row ">
<img src="{{URL::asset('storage/img/carrito/'.$item->attributes->image)}}"
alt="" class="img-fluid rounded">
<p class="mt-3 text-dark"> {{ $item->description }}</p>
</th>
<td class="pb-4"><p class="mt-3"> {{ $item->name }}</p></td>
<td></td>
<td class="pb-4">${{ $item->price }}</td>
<td>
<form action="{{ route('cart.update') }}" method="POST">
{{ csrf_field() }}
<div class="input-group mb-3">
<input type="hidden" value="{{ $item->id}}" id="id" name="id">
<input type="number" class="form-control form-control-sm "
value="{{ $item->quantity }}" id="quantity" name="quantity"
style="width: 70px; margin-right: 10px;">
<button class="btn btn-sm btn-primary btn-rounded"><i
class="fa fa-edit"></i>
</button>
</form>
<form action="{{ route('cart.remove') }}" method="POST">
{{ csrf_field() }}
<input type="hidden" value="{{ $item->id }}" id="id" name="id">
<button class="btn btn-sm btn-danger btn-rounded"><i class="fa fa-trash"></i>
</button>
</form>
</div>
</td>
</tr>
@endforeach
</tbody>
</table>
<div class="form-group text-center">
<h2 class="text-cente mt-5 text-dark">${{ \Cart::getTotal() }}</h2>
<a href="{{ route('index') }}" class="btn btn-primary btn-rounded">Proceder al CheckOut</a>
<a href="{{ route('index') }}" class="btn btn-success btn-rounded">Seguir comprando</a>
</div>
</div>
</section>
</div>
</div>
</div>
@endsection
@push('estilos')
<link rel="stylesheet" href="{{URL::asset('FrontEnd/css/tienda.css')}}">
@endpush
TIENDA
index.blade.php
@extends('welcome')
@section('titulo', 'Obed Sánchez | Tienda')
@section ('imagen' , ('storage/img/uploads/blog-tecnologia-informatica-redes.jpg'))
@section('url' , '')
@section('estracto' , 'Bienvenido a mi blog oficial, sitio dedicado a la tienda')
@section('contenido')
<div class="container-fluid p-0">
{{-- @include('Web.Home.portada') --}}
</div>
<div id="tienda" class="container">
<div class="row justify-content-center mt-5">
<div class="col-lg-12 text-center">
<h4 class="">Productos</h4>
<hr>
<div class="row">
@foreach($products as $pro)
<div class="col-lg-3">
<div class="card" >
<img src="{{URL::asset('storage/img/carrito/'.$pro->image_path) }}"
class="card-img-top mx-auto"
alt="{{ $pro->image_path }}">
<div class="card-body text-center">
<a href="#">
<h6 class="card-title">{{ $pro->name }}</h6>
</a>
<p>${{ $pro->price }}</p>
<form action="{{ route('cart.store') }}" method="POST">
{{ csrf_field() }}
<input type="hidden" value="{{ $pro->id }}" id="id" name="id">
<input type="hidden" value="{{ $pro->name }}" id="name" name="name">
<input type="hidden" value="{{ $pro->price }}" id="price" name="price">
<input type="hidden" value="{{ $pro->description }}" id="description" name="description">
<input type="hidden" value="{{ $pro->image_path }}" id="img" name="img">
<input type="hidden" value="{{ $pro->slug }}" id="slug" name="slug">
<input type="hidden" value="1" id="quantity" name="quantity">
<div class="card-footer" style="background-color: white;">
<div class="row">
<button class="btn btn-success btn-sm" class="tooltip-test" title="add to cart">
<i class="fa fa-shopping-cart"></i> agregar al carrito
</button>
</div>
</div>
</form>
</div>
</div>
</div>
@endforeach
</div>
</div>
</div>
</div>
@endsection
@push('estilos')
<link rel="stylesheet" href="{{URL::asset('FrontEnd/css/tienda.css')}}">
@endpush
Pasos para mantener el carrito al iniciar sesión.
php artisan make:migration create_wishlist_storage_table
Schema::create('wishlist_storage', function (Blueprint $table) {
$table->string('id')->index();
$table->longText('wishlist_data');
$table->timestamps();
$table->primary('id');
});
17 - creamos el modelo y lo llenamos
php artisan make:model DatabaseStorageModel
protected $table = 'wishlist_storage';
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [
'id', 'wishlist_data',
];
/**
* Mutator for wishlist_column
* @param $value
*/
public function setWishlistDataAttribute($value)
{
$this->attributes['wishlist_data'] = serialize($value);
}
/**
* Accessor for wishlist_column
* @param $value
* @return mixed
*/
public function getWishlistDataAttribute($value)
{
return unserialize($value);
}
<?php
namespace App;
use Darryldecode\Cart\CartCollection;
class DatabaseStorage {
public function has($key)
{
return ('App\Models\DatabaseStorageModel')::find($key);
}
public function get($key)
{
if($this->has($key))
{
return new CartCollection('App\Models\DatabaseStorageModel'::find($key)->wishlist_data);
}
else
{
return [];
}
}
public function put($key, $value)
{
if($row = ('App\Models\DatabaseStorageModel')::find($key))
{
// update
$row->wishlist_data = $value;
$row->save();
}
else
{
('App\Models\DatabaseStorageModel')::create([
'id' => $key,
'wishlist_data' => $value
]);
}
}
}
php artisan vendor:publish --provider="Darryldecode\Cart\CartServiceProvider" --tag="config"
Cambiamos el storage null por este
'storage' => \App\DatabaseStorage::class,
Crear usuario con tinker
php artisan tinker
$user = new App\Models\User;
$user->name = "obed";
$user->email = "[email protected]";
$user->password = Hash::make("123456789");
$user->save();
Por ultimo ejecutamos nuevamente
Php artisan migrate
Listo, ya tendríamos el carrito con Laravel y el paquete DarrylDecode funcionando perfectamente.
Solamente nos quedaría descargar los archivos necesarios, css.js e imágenes, a continuación esta repositorio para su descarga.
REPOSITORIO GITHUB
https://github.com/ManaTums/carrito.git
Etiquetas:
Gusto por las motos Harley Davidson, el rock n roll y la informática, creador de este blog para difusión del conocimiento libre, interesado en el mundo open source.
Como crear carrito de compras por usuario Laravel
Agregar reglas a usuario en Fortigate firewall
Como crear validaciones con Form Request en Laravel | Tutorial
Como instalar sanitizador para Laravel Stevebauman | Purify
Instalar Laravel + Vuejs + Vite + Como configurar, Paso Por Paso
Soluciona cualquier problema de red e impresoras compartidas en windows