Tired of Writing Image Upload Code ? Create this Reusable Service In Laravel .

Code Axion The Security Breach
5 min readFeb 12, 2023

--

Do you write image upload code ? if yes what do you do if you want to use the that code for 2 to 3 different models you make different service classes to do it right ? But, what if I told you that instead of creating multiple services, you could create just one service that can be used across all multiple sections ? , wouldn’t it be cool ?

Lets start by creating a service called ImageUploadService.php in the Services folder .

Now lets define a constructor in this class which will accept 3 parameters .

1st. Object type declaration as a parameter which will be the object of the model which we are gonna use for the image upload .

2nd. The actual image file which we we will get from the form .

3rd. The path where we will store the image in the public folder .

<?php

namespace App\Services;

class ImageUploadService{

public $image;
public $path;
public $obj;

function __construct(object $obj,$image = null,$path = null) //accepts object as a parameter
{
$this->obj = $obj; <-------- Your Model Object eg:- Product
$this->image = $image; <---- Your image file from the form
$this->path = $path; <------ Your path where you want to store that file
}

}

Now first lets define imageUpload() method.

First we will check if the image exists and is not null and after that we will store the image to the folder by using the store() method and specifying the path in the parameter of where we want to put that image, the path will be the same which we defined in the constructor and finally we will return the object it self.

<?php

namespace App\Services;

class ImageUploadService{

public $image;
public $path;
public $obj;

function __construct(object $obj,$image,$path) //accepts object as a parameter
{
$this->obj = $obj; <-------- Your Model Object eg:- Product
$this->image = $image; <---- Your image file from the form
$this->path = $path; <------ Your path where you want to store that file
}


public function uploadImage()
{

if($this->image && $this->image !== null){

//you can use store method to store the image to the folder
//by specifying the image path .

$this->image->store('public/'. $this->path . '/');

return $this;
}

return $this;
}


}

This section is storing the image to the folder now we have to save that image to the database.

Lets define 2nd method which is storeImageDB() .

Now storeImageDB() method will accept 1 parameter which will be the column name of where you want to store the image path.

so the fieldName would be dynamic it could be anything like avatar, profile, logo etc…

We cannot hard code the property like this : $this->obj->avatar

so in order to make this property dynamic we could using curly braces around the object property like this :

$dynamicProperty = 'avatar'; 

$this->obj->{$dynamicProperty} <------ results as : $this->obj->avatar

The next step is to define which object property we will use to store the image, which is : $this->obj->avatar

and the value would be the path + the image name added with md5 hash and we will return the object .

and later on we will execute this line on the controller which will save the image to the DB .

public function storeImageDB($fieldName)
{

if($fieldName && $this->image){

$this->obj->{$fieldName} = $this->path . '/' . $this->image->hashName();

//result: $this->obj->avatar = '/product_images/0Dq4n3h0frEhi8AQCJULdtz.png/'

return $this->obj;
}

return $this;
}

Now lets write code for deleting the image .

Lets define deleteImage() method:

This method will also accept one parameter, which is of course the field name, since we are checking if the object property product->avatar image exists in both the database and the folder . If it is we will delete the image by using the unlink() method .

public function deleteImage($fieldName)
{
$storePath = public_path('storage/'. $this->obj->{$fieldName});

if($this->obj->{$fieldName} && file_exists($storePath)){

//unlink method will delete the image from the folder
unlink(public_path('storage/'.$this->obj->{$fieldName}));

return $this;
}

return $this;

}

So now our Service is ready to use !

but you will be like, ‘well hey ! you only showed us how to upload the image and delete the image , where is the update image part ? ’

You don’t need the update image method . confused ?

Well if you see for uploading the image we go in a pattern like this:

uploadImage -> storeImage to Database

But if you wanna update the image and delete the previous image you can go like this:

deleteImage -> uploadImage -> storeImage to Database

So let me show how to use this method in the controller .

For Uploading The Image:

public function storeProduct(Request $request)
{
//Do Some Validation.
$validator = $request->validate([

"name" => ['required'],
"server_image" =>['image','max:2048'],
]);

//Create the product
---> Model instance $product = Product::create([
"name" => $request->name,
]);


$image = $request->file('server_image'); <--- the image file
$path = 'product_images'; <---- the path where we want to store the image to a folder

//Assign those values to constructor which is the model instance,the image and the path
$imageservice = new ImageUploadService($product,$image,$path);

//we will upload the image first and we will store that image to the database
$imageservice->uploadImage()->storeImageDB('server_image'); //<--- the field where you want to store the value in the table.

//Save the values to the database
$product->save();

}

For Updating the Image:

public function updateProduct(Request $request,$id)
{

$product = Product::findOrFail($id);

$product->name = $request->name;

//first we will check if the request has an image or not, if not we will not update the image
if (request()->hasFile('server_image') && request('server_image') != '') {

//we will assign the model again, specify the file as the 2nd parameter
//and the 3rd parameter as the path
$imageservice = new ImageUploadService($product,$request->server_image,'product_images');

//now to update the image
//first delete the image of the product
//then upload the new image to the folder
//and save that image to the database
$imageservice->deleteImage('server_image')->uploadImage()->storeImageDB('server_image');

}

$product->update(); //update the product

}

For Deleting the Image:

public function deleteProduct($id)
{
$product = Product::findOrFail($id);

$imageservice = new ImageUploadService($product); //assign the model
$imageservice->deleteImage('server_image'); //and delete the image from the folder
}

I hope you find this article useful , do give it a share among communities and members .

Happy Coding !

--

--

Code Axion The Security Breach

A Developer Who Enjoys Code Refactoring, Optimizing, and Improving The performance of Applications