In this tutorial, you will discover step by step Laravel 11 CRUD with Image Upload Tutorial example.
CRUD stands for Create, Read, Update, and Delete, and it is a term used to describe the four basic operations that can be performed on data. CRUD is commonly used in computer programming, particularly in relation to databases and web applications, to refer to the fundamental actions that can be performed on a database or other data store. You Can Learn How to create ajax dependent dropdown in laravel 11
We will create a product CRUD application using Laravel 11 in this example. We will create a products table with name, detail and image columns using Laravel 11 migration. Then, we will create routes, a controller, views, and model files for the product module. We will use Bootstrap 5 for design. Then we will create “images” folder in public folder to store images. So, let’s follow the steps below to create CRUD operations with Laravel 11.
Step for Laravel 11 CRUD with Image Upload Tutorial
Step 1: Install Laravel 11
First of all, we need to get a fresh Laravel 11 version application using the command below because we are starting from scratch. So, open your terminal or command prompt and run the command below:
composer create-project laravel/laravel crud-app
cd crud-app
Step 2: MySQL Database Configuration
In Laravel 11, there is a default database connection using SQLite, but if we want to use MySQL instead, we need to add a MySQL connection with the database name, username, and password to the `.env` file.
.env
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=here your database name(blog)
DB_USERNAME=here database username(root)
DB_PASSWORD=here database password(root)
Step 3: Create Migration
we are going to create crud application for product. so we have to create migration for “products” table using Laravel 11 php artisan command, so first fire bellow command:
php artisan make:migration create_products_table --create=products
After this command, you will find one file in the following path “database/migrations”, and you have to put the below code in your migration file to create the products table.
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up(): void
{
Schema::create('products', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->text('detail');
$table->string('image');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down(): void
{
Schema::dropIfExists('products');
}
};
Now you have to run this migration by following command:
php artisan migrate
Step 4: Add Controller and Model
In this step, now we should create a new controller named ProductController. In this controller, we write logic to store images. We store images in the “images” folder of the public folder. So, run the below command to create a new controller. The below controller is for creating a resource controller.
php artisan make:controller ProductController --resource --model=Product
After bellow command you will find new file in this path “app/Http/Controllers/ProductController.php”.
In this controller will create seven methods by default as bellow methods:
1)index()
2)create()
3)store()
4)show()
5)edit()
6)update()
7)destroy()
So, let’s copy bellow code and put on ProductController.php file.
app/Http/Controllers/ProductController.php
<?php
namespace App\Http\Controllers;
use App\Models\Product;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\View\View;
class ProductController extends Controller
{
/**
* Display a listing of the resource.
*
* @return response()
*/
public function index(): View
{
$products = Product::latest()->paginate(5);
return view('products.index',compact('products'))
->with('i', (request()->input('page', 1) - 1) * 5);
}
/**
* Show the form for creating a new resource.
*/
public function create(): View
{
return view('products.create');
}
/**
* Store a newly created resource in storage.
*/
public function store(Request $request): RedirectResponse
{
$request->validate([
'name' => 'required',
'detail' => 'required',
'image' => 'required|image|mimes:jpeg,png,jpg,gif,svg|max:2048',
]);
$input = $request->all();
if ($image = $request->file('image')) {
$destinationPath = 'images/';
$profileImage = date('YmdHis') . "." . $image->getClientOriginalExtension();
$image->move($destinationPath, $profileImage);
$input['image'] = "$profileImage";
}
Product::create($input);
return redirect()->route('products.index')
->with('success', 'Product created successfully.');
}
/**
* Display the specified resource.
*/
public function show(Product $product): View
{
return view('products.show', compact('product'));
}
/**
* Show the form for editing the specified resource.
*/
public function edit(Product $product): View
{
return view('products.edit', compact('product'));
}
/**
* Update the specified resource in storage.
*/
public function update(Request $request, Product $product): RedirectResponse
{
$request->validate([
'name' => 'required',
'detail' => 'required'
]);
$input = $request->all();
if ($image = $request->file('image')) {
$destinationPath = 'images/';
$profileImage = date('YmdHis') . "." . $image->getClientOriginalExtension();
$image->move($destinationPath, $profileImage);
$input['image'] = "$profileImage";
}else{
unset($input['image']);
}
$product->update($input);
return redirect()->route('products.index')
->with('success', 'Product updated successfully');
}
/**
* Remove the specified resource from storage.
*/
public function destroy(Product $product): RedirectResponse
{
$product->delete();
return redirect()->route('products.index')
->with('success', 'Product deleted successfully');
}
}
Okay, so after running the below command, you will find “app/Models/Product.php” and put the below content in Product.php file:
app/Models/Product.php
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Product extends Model
{
use HasFactory;
protected $fillable = [
'name', 'detail', 'image'
];
}
Step 5: Add Resource Route
Here, we need to add a resource route for the product CRUD application. So, open your “routes/web.php” file and add the following route.
routes/web.php
<?php
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\ProductController;
Route::resource('products', ProductController::class);
Step 6: Add Blade Files
In the last step, we have to create just blade files. So mainly, we have to create a layout file and then create a new folder “products”, then create blade files of the CRUD app. So finally, you have to create the following blade files:
1) layout.blade.php
2) index.blade.php
3) create.blade.php
4) edit.blade.php
5) show.blade.php
So let’s just create following file and put bellow code.
resources/views/products/layout.blade.php
<!DOCTYPE html>
<html>
<head>
<title>Laravel 11 CRUD with Image Upload Tutorial - ItSolutionStuff.com</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css" />
</head>
<body>
<div class="container">
@yield('content')
</div>
</body>
</html>
resources/views/products/index.blade.php
@extends('products.layout')
@section('content')
<div class="card mt-5">
<h2 class="card-header">Laravel 11 CRUD with Image Upload Tutorial - DevScriptSchool.com</h2>
<div class="card-body">
@session('success')
<div class="alert alert-success" role="alert"> {{ $value }} </div>
@endsession
<div class="d-grid gap-2 d-md-flex justify-content-md-end">
<a class="btn btn-success btn-sm" href="{{ route('products.create') }}"> <i class="fa fa-plus"></i> Create New Product</a>
</div>
<table class="table table-bordered table-striped mt-4">
<thead>
<tr>
<th width="80px">No</th>
<th>Image</th>
<th>Name</th>
<th>Details</th>
<th width="250px">Action</th>
</tr>
</thead>
<tbody>
@forelse ($products as $product)
<tr>
<td>{{ ++$i }}</td>
<td><img src="/images/{{ $product->image }}" width="100px"></td>
<td>{{ $product->name }}</td>
<td>{{ $product->detail }}</td>
<td>
<form action="{{ route('products.destroy',$product->id) }}" method="POST">
<a class="btn btn-info btn-sm" href="{{ route('products.show',$product->id) }}"><i class="fa-solid fa-list"></i> Show</a>
<a class="btn btn-primary btn-sm" href="{{ route('products.edit',$product->id) }}"><i class="fa-solid fa-pen-to-square"></i> Edit</a>
@csrf
@method('DELETE')
<button type="submit" class="btn btn-danger btn-sm"><i class="fa-solid fa-trash"></i> Delete</button>
</form>
</td>
</tr>
@empty
<tr>
<td colspan="5">There are no data.</td>
</tr>
@endforelse
</tbody>
</table>
{!! $products->withQueryString()->links('pagination::bootstrap-5') !!}
</div>
</div>
@endsection
resources/views/products/create.blade.php
@extends('products.layout')
@section('content')
<div class="card mt-5">
<h2 class="card-header">Add New Product</h2>
<div class="card-body">
<div class="d-grid gap-2 d-md-flex justify-content-md-end">
<a class="btn btn-primary btn-sm" href="{{ route('products.index') }}"><i class="fa fa-arrow-left"></i> Back</a>
</div>
<form action="{{ route('products.store') }}" method="POST" enctype="multipart/form-data">
@csrf
<div class="mb-3">
<label for="inputName" class="form-label"><strong>Name:</strong></label>
<input
type="text"
name="name"
class="form-control @error('name') is-invalid @enderror"
id="inputName"
placeholder="Name">
@error('name')
<div class="form-text text-danger">{{ $message }}</div>
@enderror
</div>
<div class="mb-3">
<label for="inputDetail" class="form-label"><strong>Detail:</strong></label>
<textarea
class="form-control @error('detail') is-invalid @enderror"
style="height:150px"
name="detail"
id="inputDetail"
placeholder="Detail"></textarea>
@error('detail')
<div class="form-text text-danger">{{ $message }}</div>
@enderror
</div>
<div class="mb-3">
<label for="inputImage" class="form-label"><strong>Image:</strong></label>
<input
type="file"
name="image"
class="form-control @error('image') is-invalid @enderror"
id="inputImage">
@error('image')
<div class="form-text text-danger">{{ $message }}</div>
@enderror
</div>
<button type="submit" class="btn btn-success"><i class="fa-solid fa-floppy-disk"></i> Submit</button>
</form>
</div>
</div>
@endsection
resources/views/products/edit.blade.php
@extends('products.layout')
@section('content')
<div class="card mt-5">
<h2 class="card-header">Edit Product</h2>
<div class="card-body">
<div class="d-grid gap-2 d-md-flex justify-content-md-end">
<a class="btn btn-primary btn-sm" href="{{ route('products.index') }}"><i class="fa fa-arrow-left"></i> Back</a>
</div>
<form action="{{ route('products.update',$product->id) }}" method="POST" enctype="multipart/form-data">
@csrf
@method('PUT')
<div class="mb-3">
<label for="inputName" class="form-label"><strong>Name:</strong></label>
<input
type="text"
name="name"
value="{{ $product->name }}"
class="form-control @error('name') is-invalid @enderror"
id="inputName"
placeholder="Name">
@error('name')
<div class="form-text text-danger">{{ $message }}</div>
@enderror
</div>
<div class="mb-3">
<label for="inputDetail" class="form-label"><strong>Detail:</strong></label>
<textarea
class="form-control @error('detail') is-invalid @enderror"
style="height:150px"
name="detail"
id="inputDetail"
placeholder="Detail">{{ $product->detail }}</textarea>
@error('detail')
<div class="form-text text-danger">{{ $message }}</div>
@enderror
</div>
<div class="mb-3">
<label for="inputImage" class="form-label"><strong>Image:</strong></label>
<input
type="file"
name="image"
class="form-control @error('image') is-invalid @enderror"
id="inputImage">
<img src="/images/{{ $product->image }}" width="300px">
@error('image')
<div class="form-text text-danger">{{ $message }}</div>
@enderror
</div>
<button type="submit" class="btn btn-success"><i class="fa-solid fa-floppy-disk"></i> Update</button>
</form>
</div>
</div>
@endsection
resources/views/products/show.blade.php
@extends('products.layout')
@section('content')
<div class="card mt-5">
<h2 class="card-header">Show Product</h2>
<div class="card-body">
<div class="d-grid gap-2 d-md-flex justify-content-md-end">
<a class="btn btn-primary btn-sm" href="{{ route('products.index') }}"><i class="fa fa-arrow-left"></i> Back</a>
</div>
<div class="row">
<div class="col-xs-12 col-sm-12 col-md-12">
<div class="form-group">
<strong>Name:</strong> <br/>
{{ $product->name }}
</div>
</div>
<div class="col-xs-12 col-sm-12 col-md-12 mt-2">
<div class="form-group">
<strong>Details:</strong> <br/>
{{ $product->detail }}
</div>
</div>
<div class="col-xs-12 col-sm-12 col-md-12">
<div class="form-group">
<strong>Image:</strong><br/>
<img src="/images/{{ $product->image }}" width="500px">
</div>
</div>
</div>
</div>
</div>
@endsection
Run Laravel App:
All the required steps have been done, now you have to type the given below command and hit enter to run the Laravel app:
php artisan serve
Now, Go to your web browser, type the given URL and view the app output:
http://localhost:8000/products
Make sure, you have created “images” folder in public directory
You will see layout as like bellow:
List Page:
Add Page:
Edit Page:
Show Page:
You can download the code from git: