Laravel 9 Image Upload Tutorial Step by Step Example

Apr 06, 2022 . Admin

Hi dev,

Today, I explian laravel 9 image upload tutorial step by step example. Laravel 9 crud example with image upload. In this tutorial, we will learn how to create crud app with image file upload and preview in laravel 9 application. laravel 9 with image upload and validation example. Laravel 9 crud image upload with validation.

This laravel 9 crud with image file upload and preview tutorial will guide step by step on how to implement crud app with image upload and preview.

So, let's start following example:

Step 1: Download Laravel

Let us begin the tutorial by installing a new laravel application. if you have already created the project, then skip following step.

composer create-project laravel/laravel example-app
Step 2: Database Configuration

In second step, we will make database configuration for example database name, username, password etc for our crud application of laravel 9. So let's open .env file and fill all details like as bellow:

.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 post. so we have to create migration for "posts" table using Laravel 9 php artisan command, so first fire bellow command:

php artisan make:migration create_posts_table --create=posts

After this command you will find one file in following path "database/migrations" and you have to put bellow code in your migration file for create posts table.

database/migrations/create_posts_table.php
<?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('posts', function (Blueprint $table) {
            $table->id();
            $table->string('title');
            $table->text('body');
            $table->string('image');
            $table->timestamps();
        });
    }
  
    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('posts');
    }
};

Now you have to run this migration by following command:

php artisan migrate
Step 4: Create Controller and Model

In this step, now we should create new controller as PostController. in this controller we write logic to store image, we store images in "images" folder of public folder. So run bellow command and create new controller. bellow controller for create resource controller.

php artisan make:controller PostController --resource --model=Post

After bellow command you will find new file in this path "app/Http/Controllers/PostController.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 PostController.php file.

app/Http/Controllers/PostController.php
<?php
  
namespace App\Http\Controllers;
  
use Illuminate\Http\Request;
use App\Models\Post;
  
class PostController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        $posts = Post::latest()->paginate(5);
    
        return view('posts.index',compact('posts'))
            ->with('i', (request()->input('page', 1) - 1) * 5);
    }
   
    /**
     * Show the form for creating a new resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function create()
    {
        return view('posts.create');
    }
    
    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    {
        $request->validate([
            'title' => 'required',
            'body' => '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";
        }
    
        Post::create($input);
     
        return redirect()->route('posts.index')
                        ->with('success','Post created successfully.');
    }
     
    /**
     * Display the specified resource.
     *
     * @param  \App\Post  $post
     * @return \Illuminate\Http\Response
     */
    public function show(Post $post)
    {
        return view('posts.show',compact('post'));
    }
     
    /**
     * Show the form for editing the specified resource.
     *
     * @param  \App\Post  $post
     * @return \Illuminate\Http\Response
     */
    public function edit(Post $post)
    {
        return view('posts.edit',compact('post'));
    }
    
    /**
     * Update the specified resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \App\Post  $post
     * @return \Illuminate\Http\Response
     */
    public function update(Request $request, Post $post)
    {
        $request->validate([
            'title' => 'required',
            'body' => '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']);
        }
          
        $post->update($input);
    
        return redirect()->route('posts.index')
                        ->with('success','Post updated successfully');
    }
  
    /**
     * Remove the specified resource from storage.
     *
     * @param  \App\Post  $post
     * @return \Illuminate\Http\Response
     */
    public function destroy(Post $post)
    {
        $post->delete();
     
        return redirect()->route('posts.index')
                        ->with('success','Post deleted successfully');
    }
}

Ok, so after run bellow command you will find "app/Models/Post.php" and put bellow content in Post.php file:

app/Models/Post.php
<?php
  
namespace App\Models;
  
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
  
class Post extends Model
{
    use HasFactory;
    
    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'title', 'body', 'image'
    ];
}
Step 5: Create Route

Here, we need to add resource route for post crud application. so open your "routes/web.php" file and add following route.

routes/web.php
<?php
  
use Illuminate\Support\Facades\Route;
  
use App\Http\Controllers\PostController;
  
/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/
    
Route::resource('posts', PostController::class);
Step 6: Create Blade Files

In last step. In this step we have to create just blade files. So mainly we have to create layout file and then create new folder "posts" then create blade files of crud app. So finally you have to create following bellow blade file:

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/posts/layout.blade.php
<!DOCTYPE html>
<html>
<head>
    <title>Laravel 9 Image Upload Tutorial Step by Step Example - Mywebtuts.com</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css" integrity="sha256-eZrrJcwDc/3uDhsdt61sL2oOBY362qM3lon1gyExkL0=" crossorigin="anonymous" />
</head>
<body>
  
<div class="container">
    @yield('content')
</div>
   
</body>
</html>
resources/views/posts/index.blade.php
@extends('posts.layout')
     
@section('content')
    <div class="row">
        <div class="col-lg-12">
            <div class="text-center mt-5">
                <h3>Laravel 9 Image Upload Tutorial Step by Step Example - Mywebtuts.com</h3>
            </div>
            <div class="text-end mb-4 mt-5">
                <a class="btn btn-primary btn-sm rounded-0" href="{{ route('posts.create') }}">+ Create New Post</a>
            </div>
        </div>
    </div>
    
    @if ($message = Session::get('success'))
        <div class="alert alert-success p-2">
            <p>{{ $message }}</p>
        </div>
    @endif
     
    <table class="table table-bordered">
        <tr>
            <th>No</th>
            <th>Image</th>
            <th>Title</th>
            <th>Body</th>
            <th width="180px">Action</th>
        </tr>
        @foreach ($posts as $post)
        <tr>
            <td>{{ ++$i }}</td>
            <td><img src="/images/{{ $post->image }}" width="100px"></td>
            <td>{{ $post->title }}</td>
            <td>{{ $post->body }}</td>
            <td>
                <form action="{{ route('posts.destroy',$post->id) }}" method="POST">
     
                    <a class="btn btn-info btn-sm text-white rounded-0" href="{{ route('posts.show',$post->id) }}">Show</a>
      
                    <a class="btn btn-primary btn-sm rounded-0" href="{{ route('posts.edit',$post->id) }}">Edit</a>
     
                    @csrf
                    @method('DELETE')
        
                    <button type="submit" class="rounded-0 btn btn-sm btn-danger">Delete</button>
                </form>
            </td>
        </tr>
        @endforeach
    </table>
    
    {!! $posts->links() !!}
        
@endsection
resources/views/posts/create.blade.php
@extends('posts.layout')
  
@section('content')
<div class="row">
    <div class="col-lg-12 mt-5">
        <div class="pull-left">
            <h2>Add New Post</h2>
        </div>
        <div class="text-end">
            <a class="btn btn-primary btn-sm rounded-0" href="{{ route('posts.index') }}">← Back</a>
        </div>
    </div>
</div>
     
@if ($errors->any())
    <div class="alert alert-danger">
        <strong>Whoops!</strong> There were some problems with your input.<br><br>
        <ul>
            @foreach ($errors->all() as $error)
                <li>{{ $error }}</li>
            @endforeach
        </ul>
    </div>
@endif
     
<form action="{{ route('posts.store') }}" method="POST" enctype="multipart/form-data">
    @csrf
    
     <div class="row">
        <div class="col-xs-12 col-sm-12 col-md-12">
            <div class="form-group ">
                <strong>Title:</strong>
                <input type="text" name="title" class="form-control" placeholder="Title">
            </div>
        </div>
        <div class="col-xs-12 col-sm-12 col-md-12 mt-2">
            <div class="form-group">
                <strong>Body:</strong>
                <textarea class="form-control" style="height:150px" name="body" placeholder="Body"></textarea>
            </div>
        </div>
        <div class="col-xs-12 col-sm-12 col-md-12 mt-2">
            <div class="form-group">
                <strong>Image:</strong>
                <input type="file" name="image" class="form-control" placeholder="image">
            </div>
        </div>
        <div class="col-xs-12 col-sm-12 col-md-12 text-center mt-3">
            <button type="submit" class="btn btn-success rounded-0"><i class="fa fa-save"></i> Submt</button>
        </div>
    </div>
     
</form>
@endsection
resources/views/posts/edit.blade.php
@extends('posts.layout')
     
@section('content')
    <div class="row">
        <div class="col-lg-12 mt-5">
            <div class="pull-left">
                <h2>Edit Post</h2>
            </div>
            <div class="pull-right">
                <a class="btn btn-primary btn-sm rounded-0" href="{{ route('posts.index') }}">← Back</a>
            </div>
        </div>
    </div>
     
    @if ($errors->any())
        <div class="alert alert-danger">
            <strong>Whoops!</strong> There were some problems with your input.<br><br>
            <ul>
                @foreach ($errors->all() as $error)
                    <li>{{ $error }}</li>
                @endforeach
            </ul>
        </div>
    @endif
    
    <form action="{{ route('posts.update',$post->id) }}" method="POST" enctype="multipart/form-data"> 
        @csrf
        @method('PUT')
     
         <div class="row">
            <div class="col-xs-12 col-sm-12 col-md-12">
                <div class="form-group">
                    <strong>Title:</strong>
                    <input type="text" name="title" value="{{ $post->title }}" class="form-control" placeholder="Name">
                </div>
            </div>
            <div class="col-xs-12 col-sm-12 col-md-12 mt-2">
                <div class="form-group">
                    <strong>Body:</strong>
                    <textarea class="form-control" style="height:150px" name="body" placeholder="Detail">{{ $post->body }}</textarea>
                </div>
            </div>
            <div class="col-xs-12 col-sm-12 col-md-12 mt-2">
                <div class="form-group">
                    <strong>Image:</strong>
                    <input type="file" name="image" class="form-control" placeholder="image">
                    <img src="/images/{{ $post->image }}" width="200px" class="mt-2">
                </div>
            </div>
            <div class="col-xs-12 col-sm-12 col-md-12 text-center">
              <button type="submit" class="btn btn-success rounded-0"><i class="fa fa-save"></i> Submit</button>
            </div>
        </div>
     
    </form>
@endsection
resources/views/posts/show.blade.php
@extends('posts.layout')
   
@section('content')
    <div class="row">
        <div class="col-lg-12 mt-5">
            <div class="pull-left">
                <h2> Show Post</h2>
            </div>
            <div class="pull-right">
                <a class="btn btn-primary btn-sm rounded-0" href="{{ route('posts.index') }}">← Back</a>
            </div>
        </div>
    </div>
     
    <div class="row">
        <div class="col-xs-12 col-sm-12 col-md-12 mt-3">
            <div class="form-group">
                <strong>Name:</strong>
                {{ $post->title }}
            </div>
        </div>
        <div class="col-xs-12 col-sm-12 col-md-12 mt-3">
            <div class="form-group">
                <strong>Details:</strong>
                {{ $post->body }}
            </div>
        </div>
        <div class="col-xs-12 col-sm-12 col-md-12 mt-3">
            <div class="form-group">
                <strong>Image:</strong><br>
                <img src="/images/{{ $post->image }}" width="500px">
            </div>
        </div>
    </div>
@endsection
Run Laravel App:

All steps have been done, now you have to type the given command and hit enter to run the laravel app:

php artisan serve

Now, you have to open web browser, type the given URL and view the app output:

http://localhost:8000/posts
Make sure, you have created "images" folder in public directory

You will see layout as like bellow:

Output:

List Page:

Add Page:

Edit Page:

Show Page:

I hope it can help you....

#Laravel 9