Already I have discussed how to create a complete crud application in Laravel 9 application. I showed using query builder and also eloquent ORM. But there is no image upload system in those previous tutorials. So in this tutorial, I am going to create a complete crud (create, read, update, delete) system in laravel 9 with image upload.

From this tutorial, you will learn how to upload an image in laravel 9 application and also how to update image in laravel 9. I will create a User crud system and there will be name, email, password and image fields. I will upload image to storage folder and then we will link the storage directory to the public directory to display the image in laravel. For that, we have to run the storage:link command artisan command.

So if you are new to laravel and going to learn a crud system in laravel 9 application, then this laravel 9 crud with image upload tutorial is for you. I will use Laravel default User model to create this laravel crud with image upload tutorial. Just i will add image field to users table. 

I will use a resource controller to create this crud example with image upload in Laravel. I will also use model binding to fetch data very easily. So you will also learn from this tutorial how to fetch data using model binding in laravel. I will create a system where you will find the user list, user create system, user update system and user delete and showing system,

Let's start laravel crud example with image upload tutorial step by step. Before starting, I will show you some preview images that what we are going to make. To see the preview images below:

User List Page

laravel-9-crud-with-image-upload

Create User Form

create-user-form-for-image-upload-crud-laravel

User Details Page

laravel-9-crud-image-upload

Update User List Page

laravel-crud-source-code-with-image-uploading-system

Step 1: Download Fresh Laravel

In this first step, we need a fresh Laravel 9 application for the laravel 9 crud with image upload tutorial. So download it by the below command:

composer create-project laravel/laravel example-app

 

Step 2: Create Migration

We are going to use the User model. So no need to create a model and migration. Just update by adding an image uploading system which means an image column to the users table like below:

Now update the migration like below:

database/migrations

<?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()
    {
        Schema::create('users', function (Blueprint $table) {
            $table->id();
            $table->string('name');
            $table->string('email')->unique();
            $table->timestamp('email_verified_at')->nullable();
            $table->string('password');
            $table->string('image')->nullable();
            $table->rememberToken();
            $table->timestamps();
        });
    }

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

 

And now update the model like:

app/Models/User.php

<?php

namespace App\Models;

use Laravel\Sanctum\HasApiTokens;
use Illuminate\Notifications\Notifiable;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;

class User extends Authenticatable implements MustVerifyEmail
{
    use HasApiTokens, HasFactory, Notifiable;

    protected $fillable = [
        'name',
        'email',
        'password',
        'image'
    ];
}

 

Step 3: Connect database

After successfully installing the laravel app and then configuring the database setup. We will open the ".env" file and change the database name, username, and password in the env file to create a crud laravel 9 source code with image upload.

.env

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=Enter_Your_Database_Name
DB_USERNAME=Enter_Your_Database_Username
DB_PASSWORD=Enter_Your_Database_Password

 

Now run php artisan migrate command to update the database. 

php artisan migrate

 

Read also: Laravel 9 Pagination Example With Bootstrap

 

Step 4:  Create Route

Now in this, create a resource route like the one below to complete the crud application in Laravel. I am going to use a resource controller. So define the resource route like the below:

routes/web.php

<?php

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

Route::resource('user',UserController::class);

 

Now run php artisan route:list command to check the available route which we are going to use for user crud with ima. After running the command you will see the below output.

laravel-user-crud-image-upload-resource-controller

Read also:  Laravel 9 CRUD Tutorial Using Query Builder

 

Step 5: Create Controller

Now in this step, we have to create a UserController to define this method to create a crud laravel 9 bootstrap application with image upload.

php artisan make:controller UserController

 

Now update the controller like the below:

app/Http/Controllers/UserController.php

<?php

namespace App\Http\Controllers;

use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;

class UserController extends Controller
{
    public function index()
    {
        $users = User::query()->latest()->paginate(10);

        return view('user.index',compact('users'));
    }

    public function create()
    {
        return view('user.create');
    }

    public function store(Request $request)
    {   
        $request->validate([
            'name' => 'required',
            'email' => 'required|email|unique:users',
            'password' => 'required|min:6',
            'image' => 'required|image|mimes:jpeg,png,jpg,gif,svg|max:2048'
        ]);

        $fileName = time() . '.' . $request->image->extension();
        $request->image->storeAs('public/images', $fileName);
        
        $user = new User;
        $user->name = $request->input('name');
        $user->email = trim($request->input('email'));
        $user->password = bcrypt($request->input('password'));
        $user->image = $fileName;
        $user->save();

        return redirect()->route('user.index')->with([
            'message' => 'User added successfully!', 
            'status' => 'success'
        ]);
    }

    public function show(User $user)
    {
        return view('user.show',compact('user'));
    }

    public function edit(User $user)
    {
        return view('user.edit',compact('user'));
    }

    public function update(Request $request, User $user)
    {   
        $fileName = '';

        if ($request->hasFile('image')) {
          $fileName = time() . '.' . $request->image->extension();
          $request->image->storeAs('public/images', $fileName);
          if ($user->image) {
            Storage::delete('public/images/' . $user->image);
          }
        } else {
          $fileName = $user->image;
        }

        $user->name = $request->input('name');
        $user->email = trim($request->input('email'));
        $user->password = bcrypt($request->input('password'));
        $user->image = $fileName;
        $user->save();

        return redirect()->route('user.index')->with([
            'message' => 'User updated successfully!', 
            'status' => 'success'
        ]);
    }

    public function destroy(User $user)
    {   
        if($user->image){
            Storage::delete('public/images/' . $user->image);
        }
        $user->delete();

        return redirect()->route('user.index')->with([
            'message' => 'User deleted successfully!', 
            'status' => 'success'
        ]);
    }
}

 

Step 6: Create Views

We are almost there. Just we have to create four views files before completing laravel 9 crud with image upload.

  • index.balde.php
  • create.blade.php
  • edit.blade.php
  • show.blade.php

So create these files inside the following path and update them like below:

resources/views/user/index.blade.php

@extends('layouts.app')

@push('style')
<style type="text/css">
    .my-active span{
        background-color: #5cb85c !important;
        color: white !important;
        border-color: #5cb85c !important;
    }
    ul.pager>li {
        display: inline-flex;
        padding: 5px;
    }
</style>
@endpush
@section('content')
<div class="container">
    <div class="row justify-content-center">
        <div class="col-md-6">
            <div class="card p-2 mb-2" style="font-weight: 700">User CRUD Tutorial With Image / File Upload - Laravelia</div>
            <div class="card">
                <div class="card-header" style="background: gray; color:#f1f7fa; font-weight:bold;">
                    User List
                    <a href="{{ route('user.create') }}" class="btn btn-success btn-xs py-0 float-end">+ Create New</a>
                </div>
                @if(session('message'))
                <div class="alert alert-{{ session('status') }} alert-dismissible fade show" role="alert">
                    <strong>{{ session('message') }}</strong>
                    <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
                </div>
                @endif
                 <div class="card-body">                    
                    <table class="table-responsive" style="width: 100%">
                        <thead>
                            <th>#</th>
                            <th>Name</th>
                            <th>Email</th>
                            <th>Profile Pic</th>
                        </thead>
                        <tbody>
                            @foreach($users as $user)
                            <tr>
                                <td>{{ $loop->index + 1 }}</td>
                                <td>{{ $user->name }}</td>
                                <td>{{ $user->email }}</td>
                                <td>
                                    @if($user->image)
                                    <img src="{{ asset('storage/images/'.$user->image) }}" style="height: 50px;width:100px;">
                                    @else 
                                    <span>No image found!</span>
                                    @endif
                                </td>
                                <td><a href="{{ route('user.edit',$user->id) }}" class="btn btn-success btn-xs py-0">Edit</a></td>
                                <td><a href="{{ route('user.show',$user->id) }}" class="btn btn-secondary btn-xs py-0">Show</a></td>
                                <td>
                                    <form method="POST" action="{{ route('user.destroy',$user->id) }}">
                                        @csrf
                                        @method('delete')
                                        <button type="submit" class="btn btn-danger btn-xs py-0 text-danger">Delete</button>
                                    </form>
                                </td>
                            </tr>
                            @endforeach
                        </tbody>
                    </table>
                    <center class="mt-5">
                        {{  $users->links() }}
                    </center>
                </div>
            </div>
        </div>
    </div>
</div>
@endsection

 

resources/views/user/edit.blade.php

@extends('layouts.app')

@push('style')
@section('content')
<div class="container">
    <div class="row justify-content-center">
        <div class="col-md-6">
            <div class="card">
                <div class="card-header" style="background: gray; color:#f1f7fa; font-weight:bold;">
                    Update User
                    <a href="{{ route('user.index') }}" class="btn btn-success btn-xs py-0 float-end">Back</a>
                </div>
                @if($errors->any())
                    {!! implode('', $errors->all('<div>:message</div>')) !!}
                @endif
                 <div class="card-body">                    
                    <form class="w-px-500 p-3 p-md-3" action="{{ route('user.update',$user->id) }}" method="post" enctype="multipart/form-data">
                        @csrf
                        @method('patch')
                        <div class="row mb-3">
                            <label class="col-sm-3 col-form-label">Name</label>
                            <div class="col-sm-9">
                                <input type="text" class="form-control" name="name" placeholder="Name" @error('name') is-invalid @enderror value="{{ $user->name }}">
                                @error('name')
                                    <span class="invalid-feedback" role="alert">
                                        <strong>{{ $message }}</strong>
                                    </span>
                                @enderror
                            </div>
                        </div>
                
                        <div class="row mb-3">
                            <label class="col-sm-3 col-form-label">Email</label>
                            <div class="col-sm-9">
                                <input type="email" class="form-control" name="email" placeholder="Email" @error('email') is-invalid @enderror value="{{ $user->email }}">
                                @error('email')
                                    <span class="invalid-feedback" role="alert">
                                        <strong>{{ $message }}</strong>
                                    </span>
                                @enderror
                            </div>
                        </div>

                        <div class="row mb-3">
                            <label class="col-sm-3 col-form-label">Profile Pic</label>
                            <div class="col-sm-9">
                                <input type="file" class="form-control" name="image" @error('image') is-invalid @enderror>
                                @if($user->image)
                                    <img src="{{ asset('storage/images/'.$user->image) }}" style="height: 50px;width:100px; margin-top:5px;">
                                @else 
                                    <span>No image found!</span>
                                @endif
                            </div>
                            @error('image')
                                <span class="invalid-feedback" role="alert">
                                    <strong>{{ $message }}</strong>
                                </span>
                            @enderror
                        </div>

                        <div class="row mb-3">
                            <label class="col-sm-3 col-form-label"></label>
                            <div class="col-sm-9">
                                <button type="submit" class="btn btn-secondary btn-block text-danger">Submit</button>
                            </div>
                        </div>
                      </form>
                </div>
            </div>
        </div>
    </div>
</div>
@endsection

 

resources/views/user/show.blade.php

@extends('layouts.app')

@push('style')
@section('content')
<div class="container">
    <div class="row justify-content-center">
        <div class="col-md-6">
            <div class="card">
                <div class="card-header" style="background: gray; color:#f1f7fa; font-weight:bold;">
                    User details
                    <a href="{{ route('user.index') }}" class="btn btn-success btn-xs py-0 float-end">Back</a>
                </div>
                 <div class="card-body">                    
                    <div class="row mb-3">
                        <label class="col-sm-3 col-form-label">Name</label>
                        <div class="col-sm-9">
                            <input type="text" class="form-control" name="name" value="{{ $user->name }}">
                        </div>
                    </div>
            
                    <div class="row mb-3">
                        <label class="col-sm-3 col-form-label">Email</label>
                        <div class="col-sm-9">
                            <input type="email" class="form-control" name="email" value="{{ $user->email }}">
                        </div>
                    </div>

                    <div class="row mb-3">
                        <label class="col-sm-3 col-form-label">Profile Pic</label>
                        <div class="col-sm-9">
                            @if($user->image)
                                <img src="{{ asset('storage/images/'.$user->image) }}" style="height: 50px;width:100px;">
                            @else 
                                <span>No image found!</span>
                            @endif
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>
@endsection

 

resources/views/user/create.blade.php

@extends('layouts.app')

@push('style')
@section('content')
<div class="container">
    <div class="row justify-content-center">
        <div class="col-md-6">
            <div class="card">
                <div class="card-header" style="background: gray; color:#f1f7fa; font-weight:bold;">
                    Create New User
                    <a href="{{ route('user.index') }}" class="btn btn-success btn-xs py-0 float-end">Back</a>
                </div>
                @if($errors->any())
                    {!! implode('', $errors->all('<div>:message</div>')) !!}
                @endif
                 <div class="card-body">                    
                    <form class="w-px-500 p-3 p-md-3" action="{{ route('user.store') }}" method="post" enctype="multipart/form-data">
                        @csrf
                        <div class="row mb-3">
                            <label class="col-sm-3 col-form-label">Name</label>
                            <div class="col-sm-9">
                                <input type="text" class="form-control" name="name" placeholder="Name" @error('name') is-invalid @enderror>
                                @error('name')
                                    <span class="invalid-feedback" role="alert">
                                        <strong>{{ $message }}</strong>
                                    </span>
                                @enderror
                            </div>
                        </div>
                
                        <div class="row mb-3">
                            <label class="col-sm-3 col-form-label">Email</label>
                            <div class="col-sm-9">
                                <input type="email" class="form-control" name="email" placeholder="Email" @error('email') is-invalid @enderror>
                                @error('email')
                                    <span class="invalid-feedback" role="alert">
                                        <strong>{{ $message }}</strong>
                                    </span>
                                @enderror
                            </div>
                        </div>

                        <div class="row mb-3">
                            <label class="col-sm-3 col-form-label">Password</label>
                            <div class="col-sm-9">
                                <input type="password" class="form-control" name="password" placeholder="Password" @error('password') is-invalid @enderror>
                                @error('password')
                                    <span class="invalid-feedback" role="alert">
                                        <strong>{{ $message }}</strong>
                                    </span>
                                @enderror
                            </div>
                        </div>

                        <div class="row mb-3">
                            <label class="col-sm-3 col-form-label">Profile Pic</label>
                            <div class="col-sm-9">
                              <input type="file" class="form-control" name="image" @error('image') is-invalid @enderror>
                            </div>
                            @error('image')
                                <span class="invalid-feedback" role="alert">
                                    <strong>{{ $message }}</strong>
                                </span>
                            @enderror
                        </div>

                        <div class="row mb-3">
                            <label class="col-sm-3 col-form-label"></label>
                            <div class="col-sm-9">
                                <button type="submit" class="btn btn-secondary btn-block text-danger">Submit</button>
                            </div>
                        </div>
                      </form>
                </div>
            </div>
        </div>
    </div>
</div>
@endsection

 

Now we need to create a master file. So let's create a app.blade.php file and add it to the following path:

resources/views/layouts/app.blade.php

<!doctype html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <!-- CSRF Token -->
    <meta name="csrf-token" content="{{ csrf_token() }}">

    <title>{{ config('app.name', 'Laravel') }}</title>
    
    <!-- Tailwindcss -->
    <script src="https://cdn.tailwindcss.com"></script>

    <!-- Scripts -->
    @vite(['resources/sass/app.scss', 'resources/js/app.js'])
    @stack('style')
</head>
<body>
    <div id="app">
        <nav class="navbar navbar-expand-md navbar-light bg-white shadow-sm">
            <div class="container">
                <a class="navbar-brand" href="{{ url('/') }}">
                    Laravelia
                </a>
                <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="{{ __('Toggle navigation') }}">
                    <span class="navbar-toggler-icon"></span>
                </button>

                <div class="collapse navbar-collapse" id="navbarSupportedContent">
                    <!-- Left Side Of Navbar -->
                    <ul class="navbar-nav me-auto">

                    </ul>

                    <!-- Right Side Of Navbar -->
                    <ul class="navbar-nav ms-auto">
                        <!-- Authentication Links -->
                        @guest
                            @if (Route::has('login'))
                                <li class="nav-item">
                                    <a class="nav-link" href="{{ route('login') }}">{{ __('Login') }}</a>
                                </li>
                            @endif

                            @if (Route::has('register'))
                                <li class="nav-item">
                                    <a class="nav-link" href="{{ route('register') }}">{{ __('Register') }}</a>
                                </li>
                            @endif
                        @else
                            <li class="nav-item dropdown">
                                <a id="navbarDropdown" class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false" v-pre>
                                    {{ Auth::user()->name }}
                                </a>

                                <div class="dropdown-menu dropdown-menu-end" aria-labelledby="navbarDropdown">
                                    <a class="dropdown-item" href="{{ route('logout') }}"
                                       onclick="event.preventDefault();
                                                     document.getElementById('logout-form').submit();">
                                        {{ __('Logout') }}
                                    </a>

                                    <form id="logout-form" action="{{ route('logout') }}" method="POST" class="d-none">
                                        @csrf
                                    </form>
                                </div>
                            </li>
                        @endguest
                    </ul>
                </div>
            </div>
        </nav>

        <main class="py-4" style="background: #f1f7fa;">
            @yield('content')
        </main>
    </div>
    @stack('script')
</body>
</html>

 

Now all are set to go. Now run php artisan serve command to start the development server and visit the following URL to check this laravel crud with image upload tutorial.

URL
http://localhost:8000/user

 

Read also: How To Create Master Layout In Laravel?

 

Conclusion

I have tried my best to create this crud with image upload system in laravel 9 application.Now we know laravel 9 crud with image upload. Hope this laravel crud with image upload tutorial will help you to create laravel crud example with image upload. 

Category : #laravel

Tags : #laravel , #laravel crud