Como crear carrito de compras por usuario Laravel


Escrito por zEOCk hace hace 6 meses

Compartir En redes Sociales

Facebook WhatsApp Youtube

ShoppingCart Laravel

¿Que aprenderás en esta articulo?

Crear registro de usuarios
Crear base de datos
Crear migraciones
Crear Controladores
Crear Rutas
Crear modelos

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.

1 - Instalar proyecto laravel


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"

2 - Crear base de datos


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

3 - Instalar Laravel Breeze


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

4 - Instalamos el paquete darryldecode


Este paquete es muy importante que nos sirve para tener nuestro carrito sin necesidad de introducir mucho código, simplemente agregamos unos métodos al controlados y listo ya lo tendremos funcionando, ahora a instalarlo.

composer require "darryldecode/cart"

5 - Agregamos las siguientes líneas al archivo Config/app.php

Darryldecode\Cart\CartServiceProvider::class,
'Cart' => Darryldecode\Cart\Facades\CartFacade::class,

6 - Creamos el modelo Product y su migración


php artisan make:model Product -m

7 - Agregamos los siguientes campos a la migración.


$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');

8 - Creamos un Seeder y editamos el archivo database/Seeders/ProductsTableSeeder


php artisan make:seed ProductsTableSeeder
Y llenamos con los siguientes datos

use 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',
        ]);

    }


9 - Agregamos la línea siguiente en database/seeder/DatabaseSeeder.php

$this->call(ProductsTableSeeder::class);

10 - Ejecutamos los siguientes comandos

Php artisan migrate
Php artisan db:seed
Php artisan storage:link


11 - Agregamos las rutas web


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');

12 - Creamos el controlador CartController


php artisan make:controller Web/CartController

13 - Agregamos los Métodos necesarios

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!');
    }


14 - Creamos las carpetas y archivos siguiente

Web
Partials
      header.blade.php
      footer.blade.php
      css.blade.php
      js.blade.php
Carrito
      index.blade.php
Tienda
      index.blade.php


15 - Agregamos Css y js al proyecto

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>


16 - editamos los Partials con los siguiente códigos

      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')}}">
     
  js.blade.php

    <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.

17 - Creamos una migración y la llenamos

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);
}


18 - Creamos un archivo php en App/DatabaseStorage.php

<?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
        ]);
    }
}

}


19 - Ejecutamos el siguiente comando

php artisan vendor:publish --provider="Darryldecode\Cart\CartServiceProvider" --tag="config"

20 - Editamos el archivo config/shopping_cart.php

Cambiamos el storage null por este

'storage' => \App\DatabaseStorage::class,

21 - Crear un usuario con tinker

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:


Compartir En redes Sociales

Facebook WhatsApp Youtube

Generic placeholder image
Ing. Obed Sánchez

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.