PHPackages                             webcimes/laravel-mediaforge - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [File &amp; Storage](/categories/file-storage)
4. /
5. webcimes/laravel-mediaforge

ActiveLibrary[File &amp; Storage](/categories/file-storage)

webcimes/laravel-mediaforge
===========================

Laravel file &amp; image upload service with multi-format processing (resize, convert, watermark, text overlay).

0.1.0(today)11↑2900%MITPHPPHP ^8.2

Since Mar 24Pushed todayCompare

[ Source](https://github.com/WebCimes/laravel-mediaforge)[ Packagist](https://packagist.org/packages/webcimes/laravel-mediaforge)[ RSS](/packages/webcimes-laravel-mediaforge/feed)WikiDiscussions main Synced today

READMEChangelogDependencies (5)Versions (2)Used By (0)

webcimes/laravel-mediaforge
===========================

[](#webcimeslaravel-mediaforge)

Store images and files directly in your existing model columns — no separate media library table required.

Powered by [Intervention Image](https://image.intervention.io/v3), this Laravel package lets you upload a file once and automatically generate multiple formats (thumbnail, WebP, watermark, etc.), each saved as a structured entry you can store in any JSON/text column of your choosing.

Why this package?
-----------------

[](#why-this-package)

Most media libraries (like Spatie Media Library) introduce a dedicated `media` table that links files to models through a polymorphic relationship. This works great for complex scenarios, but adds overhead when you just want to attach one or a few images to a model.

**With this package:**

- Image data (path, dimensions, format config) is stored directly in whichever column you choose — a JSON column, a `text` column, even inside a JSON API response.
- No extra table, no polymorphic join, no extra migration.
- The upload result is a plain PHP array — store it anywhere, serialize it however you like.
- Regenerate derivative formats at any time from the stored original.

Features
--------

[](#features)

- Fluent `ImageFormat` builder — chain transforms in a readable, IDE-friendly way
- Multi-format processing in one upload (default + thumb + WebP, all at once)
- All formats of the same upload grouped in a single folder for easy management
- ULID-based unique naming (collision-proof, chronologically sortable, URL-safe)
- Plain PHP array output — no model binding required
- Regenerate derivative formats from the stored original at any time
- Works with any Laravel filesystem disk (local, S3, SFTP, …)

Requirements
------------

[](#requirements)

- PHP 8.2+
- Laravel 11, 12, or 13
- Intervention Image 3.x — requires either the **GD** or **Imagick** PHP extension

Installation
------------

[](#installation)

```
composer require webcimes/laravel-mediaforge
```

Publish the config file:

```
php artisan vendor:publish --tag="mediaforge-config"
```

Basic usage
-----------

[](#basic-usage)

```
use Webcimes\LaravelMediaforge\ImageFormat;
use Webcimes\LaravelMediaforge\Facades\MediaForge;

// Upload and generate two formats in one call:
$imageData = MediaForge::upload(
    $request->file('cover'),
    'public', // disk
    'products', // base path inside the disk
    [
        ImageFormat::make('default')->scaleDown(1920, 1080)->quality(80)->extension('webp'),
        ImageFormat::make('thumb')->cover(400, 300)->quality(65)->extension('webp'),
    ],
);

// Store $imageData directly in your model column (cast it to 'array' or 'json'):
$product->update(['cover' => $imageData]);
```

`$imageData` is a plain array — store it in any JSON column:

```
// $imageData:
[
    'default' => [
        'disk'     => 'public',
        'path'     => 'products/my-cover_01jq8z.../default.webp',
        'width'    => 1920,
        'height'   => 1080,
        'alt'      => 'my-cover',
        '_config'  => [...], // stored for regeneration
    ],
    'thumb' => [
        'disk'  => 'public',
        'path'  => 'products/my-cover_01jq8z.../thumb.webp',
        'width' => 400,
        'height'=> 300,
        'alt'   => 'my-cover',
        '_config' => [...],
    ],
]
```

ImageFormat reference
---------------------

[](#imageformat-reference)

MethodDescription`->disk('s3')`Override the storage disk for this format`->path('media/thumbs')`Override the storage directory`->extension('webp')`Convert to a specific format`->quality(75)`Encoding quality 1–100 (JPEG, WebP, AVIF, HEIC, TIFF)`->filename('hero')`Override the file name (without extension)`->suffix('_2x')`Append a suffix before the extension`->resize(w, h)`Exact dimensions — no ratio preservation`->resizeDown(w, h)`Same — only shrinks`->scale(w, h?)`Proportional fit — preserves ratio`->scaleDown(w, h?)`Same — only shrinks`->cover(w, h)`Center-crop to exact dimensions`->coverDown(w, h)`Same — only shrinks`->text('Draft', [...])`Text overlay (requires a TTF font — see config)`->watermark('/path/logo.png', [...])`Image watermark overlay`->customAttributes([...])`Custom metadata stored alongside this format entryRegenerate a format
-------------------

[](#regenerate-a-format)

Re-process derivatives from the stored original at any time — useful when you change the design:

```
$updated = MediaForge::regenerate($product->cover, [
    ImageFormat::make('thumb')->cover(200, 200)->extension('avif'),
]);

$product->update(['cover' => $updated]);
```

Delete files
------------

[](#delete-files)

```
// Deletes all files referenced in the stored entry:
MediaForge::delete($product->cover, 'public');
```

Custom base name
----------------

[](#custom-base-name)

The upload folder name is `{slug}_{ulid}` by default. Override it:

```
// Auto (default): slug + ULID  → my-photo_01jq8z...
MediaForge::upload($file, 'public', 'uploads', $formats);

// ULID only (no slug)          → 01jq8z...
MediaForge::upload($file, 'public', 'uploads', $formats, '');

// Custom prefix + ULID         → product-hero_01jq8z...
MediaForge::upload($file, 'public', 'uploads', $formats, 'product-hero');
```

Configuration
-------------

[](#configuration)

After publishing (`php artisan vendor:publish --tag="mediaforge-config"`):

```
return [
    // Image processing driver:
    //   'gd'      — Built into PHP, works on every host. Default.
    //   'imagick' — Requires ext-imagick. Better quality, native AVIF/HEIC. Recommended if available.
    //   'vips'    — Requires: composer require intervention/image-driver-vips + libvips.
    //               Fastest and lowest memory, but rarely available on shared hosting.
    'driver' => 'gd', // switch to 'imagick' if available on your server

    // Text overlay defaults. Any key passed to ImageFormat::text([...]) overrides these.
    // The default font is Montserrat Regular (TTF) bundled in the package — no setup needed.
    // To use a custom font, set an absolute path to a TTF or OTF file:
    'text' => [
        'font' => null, // defaults to Montserrat TTF bundled in vendor; override: resource_path('fonts/my-font.ttf')
        'size' => 48,
        'color' => 'rgba(255, 255, 255, .75)',
        'align' => 'center',
        'valign' => 'middle',
        'angle' => 0,
        'wrap' => 0, // max line width in px before wrapping; 0 = no wrap
    ],

    // Watermark overlay defaults.
    'watermark' => [
        'position' => 'center',
        'x' => 0,
        'y' => 0,
        'opacity' => 75,
    ],
];
```

License
-------

[](#license)

MIT

###  Health Score

38

—

LowBetter than 85% of packages

Maintenance100

Actively maintained with recent releases

Popularity4

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity35

Early-stage or recently created project

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Unknown

Total

1

Last Release

0d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/9f81f12ea92734e031e9f3d03fd7918771e210301fc3cfa12c6be4a96a3fa8b2?d=identicon)[contact@webcimes.com](/maintainers/contact@webcimes.com)

---

Top Contributors

[![WebCimes](https://avatars.githubusercontent.com/u/43851969?v=4)](https://github.com/WebCimes "WebCimes (1 commits)")

---

Tags

laravelimageresizefileuploadintervention

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/webcimes-laravel-mediaforge/health.svg)

```
[![Health](https://phpackages.com/badges/webcimes-laravel-mediaforge/health.svg)](https://phpackages.com/packages/webcimes-laravel-mediaforge)
```

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
