PHPackages                             whitecube/laravel-media - 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. whitecube/laravel-media

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

whitecube/laravel-media
=======================

Medial library for Laravel, managing model images &amp; assets

v1.0.4(1mo ago)0103↓72.2%MITPHPPHP ^8.5

Since May 27Pushed 1mo agoCompare

[ Source](https://github.com/whitecube/laravel-media)[ Packagist](https://packagist.org/packages/whitecube/laravel-media)[ RSS](/packages/whitecube-laravel-media/feed)WikiDiscussions main Synced 1w ago

READMEChangelog (5)Dependencies (4)Versions (6)Used By (0)

Laravel Media
=============

[](#laravel-media)

Easily optimize and access images stored as attributes on Eloquent models.

```
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Model;
use Whitecube\Media\Attributes\Image;

class User extends Model
{
    protected function avatar(): Attribute
    {
        return Image::attribute($this, 'avatar')
            ->variants([
                \App\Media\Images\SquareIcon::class,
                \App\Media\Images\SquareRegular::class,
                \App\Media\Images\ProfileCover::class,
                \App\Media\Images\SocialShare::class,
            ])
            ->default('square-regular')
            ->disk('public')
            ->path('users');
    }
}
```

```

```

Table of contents
-----------------

[](#table-of-contents)

1. [Installation](#installation)
2. [Defining image attributes](#defining-image-attributes)
3. [Defining image variant generators](#defining-image-variant-generators)
4. [Displaying images](#displaying-images)
5. [Roadmap](#roadmap)

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

[](#installation)

```
composer require whitecube/laravel-media
```

This package will auto-register its service provider.

> **Note**: Make sure your configured filesystem disk can generate public URLs when using images in Blade views. For Laravel's public disk, this usually means running `php artisan storage:link`.

Defining image attributes
-------------------------

[](#defining-image-attributes)

Getting started with `laravel-media` is quite simple as it mostly relies on Laravel's Mutators &amp; Casting principles. All you'll have to do is define a mutator attribute representing the image that needs to be handled on the model:

```
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Model;
use Whitecube\Media\Attributes\Image;

class Post extends Model
{
    protected function img(): Attribute
    {
        return Image::attribute($this, 'img');
    }
}
```

This will return a `Whitecube\Media\Image` instance when accessing the model's attribute, providing useful methods for a proper display of the image:

```

```

More on the [`Whitecube\Media\Image` class’s capabilities](#displaying-images) below.

> **Note**: Laravel 13 (and earlier) does not allow objects to be assigned to a model's `casts()` array. Mutator attribute methods are currently the only way to go.

### Configuring storage

[](#configuring-storage)

By default, the package uses your application's default filesystem disk. You can change the disk and directory for each image attribute:

```
protected function img(): Attribute
{
    return Image::attribute($this, 'img')
        ->disk('public')
        ->path('posts');
}
```

The model attribute will store a key representing the image. When using the filesystem repository, this key usually matches the filename or relative path inside the configured directory.

```
$post->img = 'cover.webp';
$post->save();
```

When the attribute is configured with `->path('posts')`, assigning `posts/cover.webp` will automatically be normalized to `cover.webp`.

### Defining variants

[](#defining-variants)

Variants are generated from the original file after the model is saved. You can define as many as needed in order to optimize the display, weight and format of the image for all situations.

```
protected function img(): Attribute
{
    return Image::attribute($this, 'img')
        ->variants([
            \App\Media\Images\PostThumbnail::class,
            \App\Media\Images\PostCover::class,
        ])
        ->default('post-thumbnail')
        ->disk('public')
        ->path('posts');
}
```

You can also register variants one by one:

```
return Image::attribute($this, 'img')
    ->variant(\App\Media\Images\PostThumbnail::class)
    ->variant(\App\Media\Images\PostCover::class);
```

Variant generation will be automatically queued after the model is saved. Make sure your queue worker is configured and running when assigning or updating images (`php artisan queue:work`).

### Placeholders

[](#placeholders)

A placeholder can be defined on the attribute:

```
protected function img(): Attribute
{
    return Image::attribute($this, 'img')
        ->placeholder(asset('images/placeholder.webp'));
}
```

Or directly when displaying the image:

```

```

The placeholder image will be used for `NULL` values and when the original file is not found.

### Custom getters and setters

[](#custom-getters-and-setters)

You may pass custom getter and setter callbacks to `Image::attribute()` when the stored value needs to be adapted before the package handles it:

```
protected function img(): Attribute
{
    return Image::attribute(
        model: $this,
        attribute: 'img',
        get: fn ($value) => $value,
        set: fn ($value) => $value,
    );
}
```

### Custom repositories

[](#custom-repositories)

The default repository reads files from the configured filesystem disk and does not rely on extra tables in your database. However, in some cases, for instance when building media libraries, you would need to store more information about uploaded and generated media. That is when a database-backed media repository becomes useful:

```
protected function img(): Attribute
{
    return Image::attribute($this, 'img')
        ->repository(\App\Media\DatabaseMediaRepository::class);
}
```

A repository must implement `Whitecube\Media\Repositories\MediaRepository`.

> **Note**: This package is still a work in progress. A default `DatabaseRepository` will be added in a future version.

Defining image variant generators
---------------------------------

[](#defining-image-variant-generators)

Each variant generator needs to implement the `Whitecube\Media\Generators\Variant` contract, exposing three main methods:

- `key`: the variant's name, which can be used as the image's "default" or specifically requested;
- `output`: the variant's configuration definition, used to check the variant's expectations;
- `generate`: the actual method that will be called when a concrete variant needs to be created.

```
namespace App\Media\Images;

use Whitecube\Media\MediaFile;
use Whitecube\Media\Generators\Variant;
use Whitecube\Media\Generators\Output;
use Whitecube\Media\Generators\Enums\Format;
use Intervention\Image\Laravel\Facades\Image;

class SquareRegular implements Variant
{
    public function key(): string
    {
        return 'square-regular';
    }

    public function output(): Output
    {
        return Output::make(Format::Webp)
            ->suffix($this->key())
            ->fit(width: 512, height: 512);
    }

    public function generate(Output $output): MediaFile
    {
        $image = $output->resize->apply(
            image: Image::decode($output->original->fullPath())
        );

        return $output->store($image, quality: 80);
    }
}
```

In this example, we're using `intervention/image-laravel` for our image manipulations, which has been seamlessly integrated into `whitecube/laravel-media`. You can, however, use any other library inside the `generate` method, as long as it returns a valid `Whitecube\Media\MediaFile` instance.

### Output helpers

[](#output-helpers)

The `Output` object provides a few helpers to keep variant filenames and transformations predictable:

```
return Output::make(Format::Webp)
    ->prefix('generated')
    ->suffix($this->key())
    ->scale(width: 630)
    ->useUniqueFilename();
```

Available helpers include:

- Filename handling:
    - `prefix()` and `suffix()` to customize generated filenames;
    - `useUniqueFilename()` to generate a random filename;
- Image dimension management:
    - `fit()` to resize and crop an image to the given dimensions;
    - `scale()` to resize an image while maintaining the original aspect ratio;
- File storage management:
    - `disk()` and `path()` to override where the variant should be stored;
    - `store()` to write the generated file and return a `MediaFile`. It currently only supports `intervention/image-laravel` image objects.

The package currently ships with WebP output support, but other common formats will be added (feel free to open a PR).

Displaying images
-----------------

[](#displaying-images)

Accessing an image attribute returns a `Whitecube\Media\Image` instance.

```

```

### Displaying a specific variant

[](#displaying-a-specific-variant)

Use the variant key to request a generated variant:

```

```

If the requested variant does not exist yet, `src()` falls back to the original file, then to the configured placeholder (if defined).

### Using the default variant

[](#using-the-default-variant)

When a default variant is configured on the attribute, calling `src()` without arguments will use it automatically:

```
protected function img(): Attribute
{
    return Image::attribute($this, 'img')
        ->variants([
            \App\Media\Images\PostCover::class,
        ])
        ->default('post-cover');
}
```

```

```

### Checking if an image exists

[](#checking-if-an-image-exists)

```
@if($post->img->isNotEmpty())

@endif
```

You can also use `isEmpty()`:

```
@if($post->img->isEmpty())

@endif
```

### Accessing files directly

[](#accessing-files-directly)

You can retrieve a concrete `MediaFile` instance for the original file or for a variant:

```
$original = $post->img->variant('original');
$cover = $post->img->variant('post-cover');

$url = $cover?->url();
$path = $cover?->fullPath();
```

### Casting to string

[](#casting-to-string)

The image object can be rendered as a string. It will output the same value as `src()`:

```

```

### About `alt`, `srcset` and `sizes`

[](#about-alt-srcset-and-sizes)

The `alt()` method currently returns the given fallback. In a future version, it is intended to look for a default value in the configured `MediaRepository`.

```

```

`srcset()` and `sizes()` are reserved for future responsive image support and currently return `null`.

Roadmap
-------

[](#roadmap)

- Adding a full version of the `DatabaseRepository` as the package's default media repository, enabling extension by media libraries.
- Adding new media types &amp; documents.
- Adding media collections for galleries.
- Adding responsive image helpers such as `srcset()` and `sizes()`.

###  Health Score

45

—

FairBetter than 91% of packages

Maintenance93

Actively maintained with recent releases

Popularity13

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity55

Maturing project, gaining track record

 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

Every ~5 days

Total

5

Last Release

36d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/8435657?v=4)[Whitecube](/maintainers/Whitecube)[@whitecube](https://github.com/whitecube)

---

Top Contributors

[![toonvandenbos](https://avatars.githubusercontent.com/u/5635557?v=4)](https://github.com/toonvandenbos "toonvandenbos (18 commits)")

### Embed Badge

![Health badge](/badges/whitecube-laravel-media/health.svg)

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

###  Alternatives

[unopim/unopim

UnoPim Laravel PIM

10.5k2.4k](/packages/unopim-unopim)[code16/sharp

Laravel Content Management Framework

79164.7k9](/packages/code16-sharp)[duncanmcclean/statamic-cargo

Comprehensive e-commerce addon for Statamic. Build bespoke e-commerce sites without the complexity.

3518.3k](/packages/duncanmcclean-statamic-cargo)

PHPackages © 2026

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