In this section we will see how to upload image in laravel 9 using laravel intervention package. Using laravel intervention image we can resize image before upload. For this tutorial we will create blogs crud with image upload using laravel intervention image. We will also see how to upload image, edit, resize image and delete image with database and folder. For this tutorial we use laravel breeze and tailwind css.
Step 1: Install Laravel & Connect Database
Run below command to create laravel project.
composer create-project laravel/laravel laravel-intervention
Now, you have to connect the laravel app to the database, hence open the .env configuration file and add the database credentials as suggested below.
.env
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=database_name
DB_USERNAME=database_user_name
DB_PASSWORD=database_password
Step 2: Install Breeze
Install laravel breeze via composer:
composer require laravel/breeze --dev
Next, run below command.
php artisan breeze:install
And final install Dependencies
npm install && npm run dev
php artisan migrate
Step 3: Create Blog Modal Migration and Controller
Run below command to create model, migration and controller
php artisan make:model Blog -mcr
create_blogs_table.php
public function up()
{
Schema::create('blogs', function (Blueprint $table) {
$table->id();
$table->string('title');
$table->text('content');
$table->string('image')->nullable();
$table->timestamps();
});
}
app/Models/Blog.php
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Blog extends Model
{
use HasFactory;
protected $fillable = [
'title',
'content',
'image'
];
}
web.php
Route::resource('blogs', BlogController::class);
Step 4: install Intervention Image package
run below command to install
composer require intervention/image
After you have installed Intervention Image, open your Laravel config file config/app.php and add the following lines.
In the $providers array add the service providers for this package.
Intervention\Image\ImageServiceProvider::class
Add the facade of this package to the $aliases array.
'Image' => Intervention\Image\Facades\Image::class
Now the Image Class will be auto-loaded by Laravel.
Publish configuration in Laravel
php artisan vendor:publish --provider="Intervention\Image\ImageServiceProviderLaravelRecent"
Step 5: Create Folder in Public Path
Next you need to create folder in public path, you give names like uploads, images, products.
Step 6: Perform Blog CRUD With image Upload Using Intervention Image
Next, import intervention use Image, File in controller for upload image, edit & update image, and delete image with public path.
app/Http/Controllers/BlogController.php
<?php
namespace App\Http\Controllers;
use App\Models\Blog;
use Illuminate\Http\Request;
use Image, File;
class BlogController extends Controller
{
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function index()
{
$blogs = Blog::all();
return view('blogs.index', compact('blogs'));
}
/**
* Show the form for creating a new resource.
*
* @return \Illuminate\Http\Response
*/
public function create()
{
return view('blogs.create');
}
/**
* Store a newly created resource in storage.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store(Request $request)
{
$data = $request->validate([
'title' => 'required|string|max:255',
'content' => 'required',
'image' => 'nullable|image|mimes:jpg,png,jpeg,gif,svg|max:2048'
]);
$image_name = uniqid() . '.' . $data['image']->getClientOriginalExtension();
$image_path = 'uploads/' . $image_name;
Image::make($data['image'])->resize(320, 240)->save(public_path($image_path));
$data['image'] = $image_path;
$blog = Blog::create($data);
return redirect()->route('blogs.index');
}
/**
* Display the specified resource.
*
* @param \App\Models\Blog $blog
* @return \Illuminate\Http\Response
*/
public function show(Blog $blog)
{
return view('blogs.show', compact('blog'));
}
/**
* Show the form for editing the specified resource.
*
* @param \App\Models\Blog $blog
* @return \Illuminate\Http\Response
*/
public function edit(Blog $blog)
{
return view('blogs.edit', compact('blog'));
}
/**
* Update the specified resource in storage.
*
* @param \Illuminate\Http\Request $request
* @param \App\Models\Blog $blog
* @return \Illuminate\Http\Response
*/
public function update(Request $request, Blog $blog)
{
$data = $request->validate([
'title' => 'required|string|max:255',
'content' => 'required',
'image' => 'nullable|image|mimes:jpg,png,jpeg,gif,svg|max:2048'
]);
if ($request->has('image')) {
unlink(public_path($blog->image));
$image_name = uniqid() . '.' . $data['image']->getClientOriginalExtension();
$image_path = 'uploads/' . $image_name;
Image::make($data['image'])->resize(320, 240)->save(public_path($image_path));
$data['image'] = $image_path;
} else {
$data['image'] = $blog->image;
}
$blog->update($data);
return redirect()->route('blogs.index');
}
/**
* Remove the specified resource from storage.
*
* @param \App\Models\Blog $blog
* @return \Illuminate\Http\Response
*/
public function destroy(Blog $blog)
{
$image = $blog->image;
$blog->delete();
File::delete(public_path($image));
return redirect()->route('blogs.index');
}
}
Step 7: Create Blade View File
view/blogs/create.blade.php
<x-app-layout>
<x-slot name="header">
<h2 class="text-xl font-semibold leading-tight text-gray-800">
{{ __('Blogs Create') }}
</h2>
</x-slot>
<div class="py-12">
<div class="mx-auto max-w-7xl sm:px-6 lg:px-8">
<div class="overflow-hidden bg-white shadow-sm sm:rounded-lg">
<div class="p-6 bg-white border-b border-gray-200">
<form method="POST" action="{{ route('blogs.store') }}" enctype="multipart/form-data">
@csrf
<div class="mb-6">
<label class="block">
<span class="text-gray-700 @error('title') text-red-500 @enderror">Title</span>
<input type="text" name="title"
class="block @error('title') border-red-500 bg-red-100 text-red-900 @enderror w-full mt-1 rounded-md"
placeholder="" value="{{old('title')}}" />
</label>
@error('title')
<div class="flex items-center text-sm text-red-600">
{{ $message }}
</div>
@enderror
</div>
<div class="mb-6">
<label class="block">
<span class="text-gray-700 @error('content') text-red-500 @enderror">Content</span>
<textarea
class="block @error('content') border-red-500 bg-red-100 text-red-900 @enderror w-full mt-1 rounded-md"
name="content" rows="3">{{old('content')}}</textarea>
</label>
@error('content')
<div class="flex items-center text-sm text-red-600">
{{ $message }}
</div>
@enderror
</div>
<div class="mb-6">
<label class="block">
<span class="sr-only">Choose File</span>
<input type="file" name="image"
class="block w-full text-sm text-gray-500 file:mr-4 file:py-2 file:px-4 file:rounded-full file:border-0 file:font-semibold file:bg-blue-50 file:text-blue-700 hover:file:bg-blue-100" />
</label>
@error('image')
<div class="flex items-center text-sm text-red-600">
{{ $message }}
</div>
@enderror
</div>
<button type="submit"
class="text-white bg-blue-600 rounded text-sm px-5 py-2.5">Submit</button>
</form>
</div>
</div>
</div>
</div>
</x-app-layout>
view/blogs/index.blade.php
<x-app-layout>
<x-slot name="header">
<h2 class="text-xl font-semibold leading-tight text-gray-800">
{{ __('Blogs') }}
</h2>
</x-slot>
<div class="py-12">
<div class="mx-auto max-w-7xl sm:px-6 lg:px-8">
<div class="overflow-hidden bg-white shadow-sm sm:rounded-lg">
<div class="p-6 bg-white border-b border-gray-200">
<h1 class="text-2xl text-center">Laravel 9 Blog CRUD With image Upload Using Intervention Image
</h1>
<div class="mt-1 mb-4">
<a class="px-2 py-2 text-sm text-white bg-blue-600 rounded"
href="{{ route('blogs.create') }}">{{ __('Add Blog') }}</a>
</div>
<div class="relative overflow-x-auto shadow-md sm:rounded-lg">
<table class="w-full text-sm text-left text-gray-500 dark:text-gray-400">
<thead
class="text-xs text-gray-700 uppercase bg-gray-50 dark:bg-gray-700 dark:text-gray-400">
<tr>
<th scope="col" class="px-6 py-3">
#
</th>
<th scope="col" class="px-6 py-3">
Title
</th>
<th scope="col" class="px-6 py-3">
Image
</th>
<th scope="col" class="px-6 py-3">
Edit
</th>
<th scope="col" class="px-6 py-3">
Show
</th>
<th scope="col" class="px-6 py-3">
Delete
</th>
</tr>
</thead>
<tbody>
@foreach ($blogs as $blog)
<tr class="bg-white border-b dark:bg-gray-800 dark:border-gray-700">
<th scope="row"
class="px-6 py-4 font-medium text-gray-900 dark:text-white whitespace-nowrap">
{{$blog->id}}
</th>
<td class="px-6 py-4">
{{$blog->title}}
</td>
<td class="px-6 py-4">
{{-- <img src="{{ $blog->getFirstMediaUrl('images') }}" alt="no image"
class="w-12 h-12"> --}}
<img src="{{ asset($blog->image) }}" alt="{{ asset($blog->image) }}"
class="w-12 h-12">
</td>
<td class="px-6 py-4">
<a href="{{ route('blogs.edit',$blog->id) }}">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"
stroke-width="1.5" stroke="currentColor" class="w-6 h-6 text-blue-600">
<path stroke-linecap="round" stroke-linejoin="round"
d="M16.862 4.487l1.687-1.688a1.875 1.875 0 112.652 2.652L10.582 16.07a4.5 4.5 0 01-1.897 1.13L6 18l.8-2.685a4.5 4.5 0 011.13-1.897l8.932-8.931zm0 0L19.5 7.125M18 14v4.75A2.25 2.25 0 0115.75 21H5.25A2.25 2.25 0 013 18.75V8.25A2.25 2.25 0 015.25 6H10" />
</svg>
</a>
</td>
<td class="px-6 py-4">
<a href="{{ route('blogs.show',$blog->id) }}">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"
stroke-width="1.5" stroke="currentColor" class="w-6 h-6 text-blue-600">
<path stroke-linecap="round" stroke-linejoin="round"
d="M2.036 12.322a1.012 1.012 0 010-.639C3.423 7.51 7.36 4.5 12 4.5c4.638 0 8.573 3.007 9.963 7.178.07.207.07.431 0 .639C20.577 16.49 16.64 19.5 12 19.5c-4.638 0-8.573-3.007-9.963-7.178z" />
<path stroke-linecap="round" stroke-linejoin="round"
d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" />
</svg>
</a>
</td>
<td class="px-6 py-4">
<form action="{{ route('blogs.destroy',$blog->id) }}" method="POST"
onsubmit="return confirm('{{ trans('are You Sure ? ') }}');"
style="display: inline-block;">
<input type="hidden" name="_method" value="DELETE">
<input type="hidden" name="_token" value="{{ csrf_token() }}">
<input type="submit" class="px-4 py-2 text-white bg-red-700 rounded"
value="Delete">
</form>
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</x-app-layout>
view/blogs/edit.blade.php
<x-app-layout>
<x-slot name="header">
<h2 class="text-xl font-semibold leading-tight text-gray-800">
{{ __('Blogs Edit') }}
</h2>
</x-slot>
<div class="py-12">
<div class="mx-auto max-w-7xl sm:px-6 lg:px-8">
<div class="overflow-hidden bg-white shadow-sm sm:rounded-lg">
<div class="p-6 bg-white border-b border-gray-200">
<form method="POST" action="{{ route('blogs.update',$blog->id) }}" enctype="multipart/form-data">
@csrf
@method('put')
<div class="mb-6">
<label class="block">
<span class="text-gray-700 @error('title') text-red-500 @enderror">Title</span>
<input type="text" name="title"
class="block @error('title') border-red-500 bg-red-100 text-red-900 @enderror w-full mt-1 rounded-md"
placeholder="" value="{{old('title',$blog->title)}}" />
</label>
@error('title')
<div class="flex items-center text-sm text-red-600">
{{ $message }}
</div>
@enderror
</div>
<div class="mb-6">
<label class="block">
<span class="text-gray-700 @error('content') text-red-500 @enderror">Content</span>
<textarea
class="block @error('content') border-red-500 bg-red-100 text-red-900 @enderror w-full mt-1 rounded-md"
name="content" rows="3">{{old('content',$blog->content)}}</textarea>
</label>
@error('content')
<div class="flex items-center text-sm text-red-600">
{{ $message }}
</div>
@enderror
</div>
<div class="mb-6">
<label class="block">
<span class="sr-only">Choose File</span>
<input type="file" name="image"
class="block w-full text-sm text-gray-500 file:mr-4 file:py-2 file:px-4 file:rounded-full file:border-0 file:font-semibold file:bg-blue-50 file:text-blue-700 hover:file:bg-blue-100" />
</label>
@error('image')
<div class="flex items-center text-sm text-red-600">
{{ $message }}
</div>
@enderror
<img src="{{ asset($blog->image) }}" class="w-12 h-12" alt="{{ asset($blog->image) }}">
</div>
<button type="Update"
class="text-white bg-blue-600 rounded text-sm px-5 py-2.5">Update</button>
</form>
</div>
</div>
</div>
</div>
</x-app-layout>
view/blogs/show.blade.php
<x-app-layout>
<x-slot name="header">
<h2 class="text-xl font-semibold leading-tight text-gray-800">
{{ __('Blog Show') }}
</h2>
</x-slot>
<div class="py-12">
<div class="max-w-4xl mx-auto sm:px-6 lg:px-8">
<div class="overflow-hidden bg-white shadow-sm sm:rounded-lg">
<div class="p-6 bg-white border-b border-gray-200">
<div class="flex flex-col items-center justify-center">
<h1 class="text-2xl font-bold">{{ $blog->title }}</h1>
<div>{!! $blog->content !!}</div>
<img src="{{ asset($blog->image) }}" class="w-60 h-60"alt="{{ asset($blog->image) }}">
</div>
</div>
</div>
</div>
</div>
</x-app-layout>
Step 8: Run Laravel and vite server
php artisan serve
//and next terminal
npm run dev
Read Also
Laravel 9 Upload Multiple Image Using Spatie Media Library
Laravel 9 Upload Multiple Images Tutorial Example
How to update multiple images in laravel 9
Upload Images with Spatie Media Library in Laravel 9