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 enviar correos en Angular haciendo uso de Laravel
Como instalar Admin Lte en un proyecto de Laravel con Jetstream
Como acceder a Escritorio remoto GRATIS, fuera de mi red
Instalar Darryldecode Carrito de compras En Laravel 11
Compartir y proteger carpeta con usuario y contraseña Windows
Como usar Soft Delete en Php con Laravel | Paso a paso