Uploading images is one of the most common tasks in web development. But if done naively, your controllers get cluttered with repetitive code for uploading, deleting, and managing files.

In this article, we'll create a **reusable Image Helper** in Laravel that you can use across your entire project — keeping your code **clean**, **DRY**, and **easy to maintain**.

## Problem

Most beginner Laravel developers end up writing repetitive code like this:

if ($request->hasFile('logo')) {
   $file = $request->file('logo');
   $filename = time().'_'.$file->getClientOriginalName();
   $file->move(public_path('storage/company'), $filename);
   $company->logo = 'company/' . $filename;
}

And for deleting images:

if ($company->logo) {
   $imagePath = public_path('storage/' . $company->logo);
   if (file_exists($imagePath)) {
   unlink($imagePath);
   }
}

The more image fields you have, the messier your controller becomes.

Solution: Reusable Image Helper

Instead of repeating the same code everywhere, we create a single helper that handles both uploading and deleting images. This helper can be used anywhere in your project, for logos, avatars, PDFs, or any file.

Step 1: Create the Helper

Create a file: app/Helpers/ImageHelper.php

<?php

namespace App\Helpers;

use Illuminate\Support\Facades\File;
use Illuminate\Support\Str;

class ImageHelper
{
    // Upload image
    public static function uploadImage($file, $folder, $oldFilePath = null)
    {
        // Delete old file if exists
        if ($oldFilePath) {
            self::deleteImage($oldFilePath);
        }

        // Generate a unique filename
        $filename = Str::uuid() . '_' . $file->getClientOriginalName();

        // Create folder if not exists
        $destination = public_path('storage/' . $folder);
        if (!File::exists($destination)) {
            File::makeDirectory($destination, 0755, true);
        }

        // Move file
        $file->move($destination, $filename);

        return $folder . '/' . $filename;
    }

    // Delete image
    public static function deleteImage($path)
    {
        $fullPath = public_path('storage/' . $path);
        if (File::exists($fullPath)) {
            File::delete($fullPath);
            return true;
        }
        return false;
    }
}

💡 Tip: Using Str::uuid() ensures your filenames are globally unique, avoiding conflicts if multiple users upload files simultaneously.

Step 2: Autoload the Helper

In composer.json:

"autoload": {
    "files": [
        "app/Helpers/ImageHelper.php"
    ]
}

Then run:

composer dump-autoload

Step 3: Use in Controller

Now your controller becomes super clean:

use App\Helpers\ImageHelper;

if ($request->hasFile('logo')) {
    $companyData['logo'] = ImageHelper::uploadImage(
        $request->file('logo'),
        'company',
        $company->logo // old file path to delete
    );
}

if ($request->hasFile('favicon')) {
    $companyData['favicon'] = ImageHelper::uploadImage(
        $request->file('favicon'),
        'company',
        $company->favicon
    );
}

$company->update($companyData);

Step 4: Delete Old Images (Optional)

ImageHelper::deleteImage($client->img);

This ensures no orphan files remain in your public/storage folder.

Benefits

  1. Cleaner controllers
  2. Reusable across multiple projects
  3. Handles both upload and delete
  4. Auto-creates folders
  5. Filename conflicts minimized with Str::uuid()
  6. Works perfectly with cPanel hosting

Conclusion

With this helper, you never have to repeat your file upload or delete logic. It's plug-and-play, Laravel-friendly, and fully compatible with shared hosting environments.

Whether you're building a CMS, e-commerce site, or any Laravel project, this helper saves time, keeps your code DRY, and standardizes image handling.

Next Steps / Ideas:

  • Extend the helper to handle other file types like PDFs, videos, or docs.
  • Add image resizing or thumbnails using Intervention/Image.
  • Combine with user avatars or multi-image uploads for galleries.