Let’s create a Trait to upload, resize, delete and manipulate images by Intervention Image, the Laravel & PHP image handling, and manipulation library.
Intervention Image provides an easy and expressive way to manipulate images. I have been using it for years. I did everything I want with it from resizing and adding watermarks to composing images. Its classes and functions are very easy to use, and understand how they work.
In this tutorial, we will create a Trait for uploading and resizing images then saving them in storage and deleting them as well.
If you don’t like to read, you can see this video on YouTube: Upload & Resize Images with Intervention Image In Laravel API and Create Thumbnails
Intervention Image installation
I’m using Laravel 9, let’s install it via composer
composer require intervention/image
In config/app.php
file, let’s add the following class to $providers
array
Intervention\Image\ImageServiceProvider::class
In the same file, let’s add the facade of this package to the $aliases
array.
'Image' => Intervention\Image\Facades\Image::class
Make sure PHP’s GD library extension is active
Laravel Intervention Image Trait
Let’s create a trait with all the functions we need to manipulate our images so we can call these functions whenever we want.
Create file and folder in app\Traits\ImageProcessing.php
and create our trait
<?php
namespace App\Traits;
use Image;
use Storage;
use Illuminate\Support\Str;
trait ImageProcessing{
}
The first function we create in our trait is for getting the image extension by mime of the uploaded file so we can use it in renaming the file later.
public function get_mime($mime){
if ($mime == 'image/jpeg')
$extension = '.jpg';
elseif ($mime == 'image/png')
$extension = '.png';
elseif ($mime == 'image/gif')
$extension = '.gif';
elseif ($mime == 'image/svg+xml')
$extension = '.svg';
elseif ($mime == 'image/tiff')
$extension = '.tiff';
elseif ($mime == 'image/webp')
$extension = '.webp';
return $extension ;
}
Let’s create a function for saving the image and renaming the file with a random string and date, for making sure no overriding with current or new images in our storage.
public function saveImage($image){
$img = Image::make($image);
$extension = $this->get_mime($img->mime());
$str_random = Str::random(8);
$imgpath = $str_random.time().$extension;
$img->save(storage_path('app/imagesfp').'/'.$imgpath);
return $imgpath;
}
We return the $imgpath
with the image path so we can save it in our database. We pass the storage path to $img->save()
for saving the image in it.
The next function here is for resizing the image. We will add the width and height that we want and we will use $constraint->aspectRatio();
to keep the aspect ratio of the image so that the largest side fits within the limit and the smaller side will be scaled to maintain the original aspect ratio.
public function aspect4resize($image,$width,$height){
$img = Image::make($image);
$extension = $this->get_mime($img->mime());
$str_random = Str::random(8);
$img->resize($width,$height,function($constraint){
$constraint->aspectRatio();
});
$imgpath = $str_random.time().$extension;
$img->save(storage_path('app/imagesfp').'/'.$imgpath);
return $imgpath;
}
But if we want to keep the height and only crop the width or resize it, we use the next function.
public function aspect4height($image,$width,$height){
$img = Image::make($image);
$extension = $this->get_mime($img->mime());
$str_random = Str::random(8);
$img->resize(null,$height,function($constraint){
$constraint->aspectRatio();
});
if($img->width() < $width){
$img->resize($width, null);
}
else if($img->width() > $width){
$img->crop($width, $heigh, 0, 0);
}
$imgpath = $str_random.time().$extension;
$img->save(storage_path('app/imagesfp').'/'.$imgpath);
return $imgpath;
}
We can use all the above functions separately. But if we want one function to save the original image and create thumbnails we should create the below function that returns an array will all the images’ paths.
public function saveImageAndThumbnail($Thefile,$thumb = false){
$dataX = array();
$dataX['image'] = $this->saveImage($Thefile);
if($thumb){
$dataX['thumbnailsm']= $this->aspect4resize($Thefile,256,144);
$dataX['thumbnailmd']= $this->aspect4resize($Thefile,426,240);
$dataX['thumbnailxl']= $this->aspect4resize($Thefile,640,360);
}
return $dataX;
}
Finally in our traits, the delete function. We just pass the image path from our database and it will delete it.
public function deleteImage($filePath){
if($filePath){
if(is_file(Storage::disk('imagesfp')->path($filePath))){
if(file_exists(Storage::disk('imagesfp')->path($filePath))){
unlink(Storage::disk('imagesfp')->path($filePath));
}
}
}
}
Using The trait
We call our trait in our controller like the below code.
use App\Traits\ImageProcessing;
class ProductController extends Controller
{
use ImageProcessing,
public function store(ProductStoreRequest $request)
{
//
if($request->hasFile('image')){
$dataX = $this->saveImageAndThumbnail($request->file('image'),true);
$data['image'] = $dataX['image'];
$data['thumbnailsm'] = $dataX['thumbnailsm'];
$data['thumbnailmd'] = $dataX['thumbnailmd'];
$data['thumbnailxl'] = $dataX['thumbnailxl'];
}
$product = Product::create($data);
//
}
}
To get the images’ URL, we use Laravel Storage class as the following
'image' => $this->image? Storage::disk('imagesfp')->url($this->image):'',
'thumbnailsm' => $this->thumbnailsm? Storage::disk('imagesfp')->url($this->thumbnailsm):'',
'thumbnailmd' => $this->thumbnailmd? Storage::disk('imagesfp')->url($this->thumbnailmd):'',
'thumbnailxl' => $this->thumbnailxl? Storage::disk('imagesfp')->url($this->thumbnailxl):'',