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 FileBelow 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");
});
.png)
.png)
.png)
.png)
.png)
.png)
Comments
Post a Comment