CRUD Project (Create | Read | Update | Delete) | Image Upload in Laravel 11

 <?php


namespace App\Http\Controllers;

use App\Models\Product;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Validator;

class ProductController extends Controller
{
    // This method will show products page
    public function index()
    {
        $products = Product::orderBy("created_at", "DESC")->get();
        return view("products.list", [
            "products" => $products
        ]);
    }

    // This method will show create product page
    public function create()
    {
        return view("products.create");
    }

    // This method will store a product in db
    public function store(Request $request)
    {
        $rules = [
            "name" => "required|min:5",
            "sku" => "required|min:3",
            "price" => "required|numeric"
        ];

        if ($request->image != "") {
            $rules["image"] = "image";
        }

        $validator = Validator::make($request->all(), $rules);

        if ($validator->fails()) {
            return redirect()->route("products.create")->withInput()->withErrors($validator);
        }

        // here we will insert product in db
        $product = new Product();

        $product->name = $request->name;
        $product->sku = $request->sku;
        $product->price = $request->price;
        $product->description = $request->description;
        $product->save();

        if ($request->image != "") {
            // here we will store image
            $image = $request->image;
            $ext = $image->getClientOriginalExtension();
            $imageName = time() . "." . $ext;   //Unique image name

            // Save image to products directory
            $image->move(public_path("uploads/products"), $imageName);

            // Save image name in database
            $product->image = $imageName;
            $product->save();
        }

        return redirect()->route("products.index")->with("success", "Product added successfully.");
    }

    // This method will show edit product page
    public function edit($id)
    {
        $product = Product::findOrFail($id);
        return view("products.edit", [
            "product" => $product
        ]);
    }

    // This method will update a product
    public function update($id, Request $request)
    {
        $product = Product::findOrFail($id);

        $rules = [
            "name" => "required|min:5",
            "sku" => "required|min:3",
            "price" => "required|numeric"
        ];

        if ($request->image != "") {
            $rules["image"] = "image";
        }

        $validator = Validator::make($request->all(), $rules);

        if ($validator->fails()) {
            return redirect()->route("products.edit", $product->id)->withInput()->withErrors($validator);
        }

        // here we will update product in db
        $product->name = $request->name;
        $product->sku = $request->sku;
        $product->price = $request->price;
        $product->description = $request->description;
        $product->save();

        if ($request->image != "") {
            // delete old image
            File::delete(public_path("uploads/products/" . $product->image));

            // here we will store image
            $image = $request->image;
            $ext = $image->getClientOriginalExtension();
            $imageName = time() . "." . $ext;   //Unique image name

            // Save image to products directory
            $image->move(public_path("uploads/products"), $imageName);

            // Save image name in database
            $product->image = $imageName;
            $product->save();
        }

        return redirect()->route("products.index")->with("success", "Product updated successfully.");
    }

    // This method will delete a product
    public function destroy($id)
    {
        $product = Product::findOrFail($id);

        // delete image
        File::delete(public_path("uploads/products/" . $product->image));

        // delete product from database
        $product->delete();

        return redirect()->route("products.index")->with("success", "Product deleted successfully.");
    }
}
Above File is app\Http\Controllers\ProductController.php File





Below File is app\Models\Product.php File
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Product extends Model
{
    public $timestamps = true;
    protected $table = "products";
    protected $fillable = ["name", "sku", "price", "description", "image"];
}






Below File is database\migrations\2025_01_01_090826_create_products_table File
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
    /**
     * Run the migrations.
     */
    public function up(): void
    {
        Schema::create('products', function (Blueprint $table) {
            $table->id();
            $table->string("name");
            $table->string("sku");
            $table->double("price", 10, 2);
            $table->text("description")->nullable();
            $table->string("image")->nullable();
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     */
    public function down(): void
    {
        Schema::dropIfExists('products');
    }
};






Below File is resources\views\products\create.blade.php File
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Create Page</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
</head>
<body>
    <div class="bg-dark py-3">
        <h3 class="text-white text-center">Simple Laravel 11 CRUD</h3>
    </div>
    <div class="container">
        <div class="row justify-content-center mt-4">
            <div class="col-md-10 d-flex justify-content-end">
                <a href="{{ route('products.index') }}" class="btn btn-dark">Back</a>
            </div>
        </div>
        <div class="row d-flex justify-content-center">
            <div class="col-md-10">
                <div class="card border-0 shadow-lg my-4">
                    <div class="card-header bg-dark">
                        <h3 class="text-white">Create Product</h3>
                    </div>
                    <form action="{{ route('products.store') }}" method="POST" enctype="multipart/form-data">
                        @csrf
                        <div class="card-body">
                            <div class="mb-3">
                                <label for="name" class="form-label h5">Name</label>
                                <input type="text" name="name" id="name" value="{{ old("name") }}" class="form-control form-control-lg @error("name") is-invalid @enderror" placeholder="Name"/>
                                @error("name")
                                    <p class="invalid-feedback">{{ $message }}</p>
                                @enderror
                            </div>
                            <div class="mb-3">
                                <label for="sku" class="form-label h5">Sku</label>
                                <input type="text" name="sku" id="sku" value="{{ old("sku") }}" class="form-control form-control-lg @error("sku") is-invalid @enderror" placeholder="Sku"/>
                                @error("sku")
                                    <p class="invalid-feedback">{{ $message }}</p>
                                @enderror
                            </div>
                            <div class="mb-3">
                                <label for="price" class="form-label h5">Price</label>
                                <input type="text" name="price" id="price" value="{{ old("price") }}" class="form-control form-control-lg @error("price") is-invalid @enderror" placeholder="Price"/>
                                @error("price")
                                    <p class="invalid-feedback">{{ $message }}</p>
                                @enderror
                            </div>
                            <div class="mb-3">
                                <label for="description" class="form-label h5">Description</label>
                                <textarea name="description" id="description" value="{{ old("description") }}" class="form-control" cols="30" rows="5" placeholder="Description"></textarea>
                            </div>
                            <div class="mb-3">
                                <label for="image" class="form-label h5">Image</label>
                                <input type="file" name="image" id="image" class="form-control form-control-lg" placeholder="Price"/>
                            </div>
                            <div class="d-grid">
                                <button type="submit" class="btn btn-lg btn-primary">Submit</button>
                            </div>
                        </div>
                    </form>
                </div>
            </div>
        </div>
    </div>
</body>
</html>





Below File is resources\views\products\edit.blade.php File
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Create Page</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
</head>
<body>
    <div class="bg-dark py-3">
        <h3 class="text-white text-center">Simple Laravel 11 CRUD</h3>
    </div>
    <div class="container">
        <div class="row justify-content-center mt-4">
            <div class="col-md-10 d-flex justify-content-end">
                <a href="{{ route('products.index') }}" class="btn btn-dark">Back</a>
            </div>
        </div>
        <div class="row d-flex justify-content-center">
            <div class="col-md-10">
                <div class="card border-0 shadow-lg my-4">
                    <div class="card-header bg-dark">
                        <h3 class="text-white">Edit Product</h3>
                    </div>
                    <form action="{{ route('products.update',$product->id) }}" method="POST" enctype="multipart/form-data">
                        @csrf
                        @method("PUT")
                        <div class="card-body">
                            <div class="mb-3">
                                <label for="name" class="form-label h5">Name</label>
                                <input type="text" name="name" id="name" value="{{ old("name",$product->name) }}" class="form-control form-control-lg @error("name") is-invalid @enderror" placeholder="Name"/>
                                @error("name")
                                    <p class="invalid-feedback">{{ $message }}</p>
                                @enderror
                            </div>
                            <div class="mb-3">
                                <label for="sku" class="form-label h5">Sku</label>
                                <input type="text" name="sku" id="sku" value="{{ old("sku",$product->sku) }}" class="form-control form-control-lg @error("sku") is-invalid @enderror" placeholder="Sku"/>
                                @error("sku")
                                    <p class="invalid-feedback">{{ $message }}</p>
                                @enderror
                            </div>
                            <div class="mb-3">
                                <label for="price" class="form-label h5">Price</label>
                                <input type="text" name="price" id="price" value="{{ old("price",$product->price) }}" class="form-control form-control-lg @error("price") is-invalid @enderror" placeholder="Price"/>
                                @error("price")
                                    <p class="invalid-feedback">{{ $message }}</p>
                                @enderror
                            </div>
                            <div class="mb-3">
                                <label for="description" class="form-label h5">Description</label>
                                <textarea name="description" id="description" value="{{ old("description",$product->description) }}" class="form-control" cols="30" rows="5" placeholder="Description"></textarea>
                            </div>
                            <div class="mb-3">
                                <label for="image" class="form-label h5">Image</label>
                                <input type="file" name="image" id="image" class="form-control form-control-lg" placeholder="Price"/>

                                @if($product->image != "")
                                    <img src="{{ asset('uploads/products/'.$product->image) }}" class="w-50 my-3" alt=""/>
                                @endif
                            </div>
                            <div class="d-grid">
                                <button type="submit" class="btn btn-lg btn-primary">Update</button>
                            </div>
                        </div>
                    </form>
                </div>
            </div>
        </div>
    </div>
</body>
</html>






Below File is resources\views\products\list.blade.php File
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Create Page</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
</head>
<body>
    <div class="bg-dark py-3">
        <h3 class="text-white text-center">Simple Laravel 11 CRUD</h3>
    </div>
    <div class="container">
        <div class="row d-flex justify-content-center mt-4">
            <div class="col-md-10 d-flex justify-content-end">
                <a href="{{ route('products.create') }}" class="btn btn-dark">Create</a>
            </div>
        </div>
        <div class="row d-flex justify-content-center">
            @if(Session::has("success"))
            <div class="col-md-10 mt-4">
                <div class="alert alert-success">
                    {{ Session::get("success") }}
                </div>
            </div>
            @endif
            <div class="col-md-10">
                <div class="card border-0 shadow-lg my-4">
                    <div class="card-header bg-dark">
                        <h3 class="text-white">Products</h3>
                    </div>
                    <div class="card-body">
                        <table class="table table-bordered table-striped table-hovered">
                            <thead>
                                <th>ID</th>
                                <th>Image</th>
                                <th>Name</th>
                                <th>Sku</th>
                                <th>Price</th>
                                <th>Created At</th>
                                <th>Action</th>
                            </thead>
                            @if($products->isNotEmpty())
                            @foreach($products as $data)
                                <tbody>
                                    <td>{{ $data->id }}</td>
                                    <td>
                                        @if($data->image != "")
                                            <img src="{{ asset('uploads/products/'.$data->image) }}" width="50" alt=""/>
                                        @endif
                                    </td>
                                    <td>{{ $data->name }}</td>
                                    <td>{{ $data->sku }}</td>
                                    <td>${{ $data->price }}</td>
                                    <td>{{ \Carbon\Carbon::parse($data->created_at)->format("d M, Y") }}</td>
                                    <td>
                                        <a href="{{ route('products.edit',$data->id) }}" class="btn btn-dark">Edit</a>
                                        <a href="#" onclick="deleteProduct({{ $data->id }});" class="btn btn-danger">Delete</a>
                                        <form id="delete-product-from-{{ $data->id }}" action="{{ route('products.destroy',$data->id) }}" method="POST">
                                            @csrf
                                            @method("DELETE")
                                        </form>
                                    </td>
                                </tbody>
                            @endforeach
                            @endif
                        </table>
                    </div>
                </div>
            </div>
        </div>
    </div>
</body>
</html>

<script>
    function deleteProduct(id)
    {
        if(confirm("Are you sure you want to delete product ?")) {
            document.getElementById("delete-product-from-"+id).submit();
        }
    }
</script>





Below File is routes\web.php File
<?php

use App\Http\Controllers\ProductController;
use Illuminate\Support\Facades\Route;

Route::get('/', function () {
    return view('welcome');
});

Route::controller(ProductController::class)->group(function () {
    Route::get("/products/create", "create")->name("products.create");
    Route::post("/products", "store")->name("products.store");
    Route::get("/products", "index")->name("products.index");
    Route::get("/products/{product}/edit", "edit")->name("products.edit");
    Route::put("/products/{product}", "update")->name("products.update");
    Route::delete("/products/{product}", "destroy")->name("products.destroy");
});







Comments

Popular posts from this blog

Eloquent Many to Many Relationship Tutorial in Laravel 11

Eloquent with JSON Data Columns Tutorial in Laravel 11

Blade Template Tutorial Three Template Inheritance in Laravel 11