How to Create CRUD with Image Upload in Laravel 11?

27-Apr-2024

.

Admin

How to Create CRUD with Image Upload in Laravel 11?

Hi, Dev

In this guide, you'll uncover a detailed walkthrough for implementing Laravel 11 CRUD operations with image uploading.

CRUD, short for Create, Read, Update, and Delete, encapsulates the fundamental operations for managing data, commonly utilized in programming, particularly within databases and web applications.

In this illustration, we'll craft a product CRUD application employing Laravel 11. We'll commence by crafting a products table via Laravel 11 migration, including columns such as name, detail, and image. Following that, we'll configure routes, a controller, views, and model files for the product module. Bootstrap 5 will be employed for styling purposes. Additionally, we'll establish an "images" folder within the public directory to house images. Let's proceed through the subsequent steps to implement CRUD operations with Laravel 11.

Preview:


Step for Laravel 11 CRUD and Image Upload Example

Step 1: Install Laravel 11

Step 2: MySQL Database Configuration

Step 3: Create Migration

Step 4: Create Controller and Model

Step 5: Add Resource Route

Step 6: Add Blade Files

Run Laravel App

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 example-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>How to Create CRUD with Image Upload in Laravel 11? - NiceSnippets.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">How to Create CRUD with Image Upload in Laravel 11? - NiceSnippets.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:

laravel-11-img-up-crud-list

Add Page:

laravel-11-crud-prod-add

Edit Page:

Laravel-11-crud-img-up-edit

Show Page:

laravel-11-crud-img-up-show

I hope it can help you....

#Laravel 11