Laravel-model-media

Pubblicato il 06 febbraio 2026 - Blog & Discussioni - Autore: devmentorpro

Dopo mesi di riflessione su come semplificare la gestione dei media in Laravel senza aggiungere complessità inutile, sono orgoglioso di presentare Laravel Model Media: un package che risolve il problema del media management eliminando tabelle aggiuntive e relazioni complesse. Zero boilerplate, massima semplicità, gestione automatica completa.

Il Problema

Quando lavori su applicazioni Laravel, prima o poi ti trovi a dover gestire file caricati dagli utenti: avatar, documenti, immagini di copertina. La maggior parte degli sviluppatori si affida a package come Spatie MediaLibrary, che sono potenti ma introducono una complessità spesso eccessiva per casi d'uso semplici.

// ❌ Con Spatie MediaLibrary: tabelle aggiuntive, relazioni polymorphic
class User extends Model implements HasMedia
{
    use InteractsWithMedia;

    public function registerMediaCollections(): void
    {
        $this->addMediaCollection('avatar')->singleFile();
    }
}

// Ogni file richiede una query extra al database
$user->getFirstMediaUrl('avatar');  // Extra JOIN sulla tabella `media`

Devi migrare una nuova tabella media, gestire relazioni polymorphic, e ogni volta che recuperi un file devi fare una query aggiuntiva. Per un semplice avatar o un documento PDF, sembra davvero troppo.

La Soluzione

Laravel Model Media adotta un approccio radicalmente diverso: usa le colonne che già hai. Niente tabelle extra, niente relazioni complesse, solo un trait intelligente che gestisce tutto automaticamente.

// ✅ Con Laravel Model Media: usa le tue colonne esistenti
class User extends Model
{
    use HasMedia;

    protected static function booted()
    {
        self::registerMediaForColumn(
            column: 'profile_photo',
            directory: 'avatars',
            fileName: 'id',
            disk: 'public'
        );
    }
}

// Caricamento: una riga
$user->attachMedia($request->file('photo'), 'profile_photo');

// Recupero URL: zero query extra
$url = $user->getMediaUrl('profile_photo');

Perché Ho Creato Laravel Model Media

L'idea è nata da un'esigenza concreta. Stavo sviluppando diverse applicazioni Laravel dove i requisiti di media management erano semplici: un avatar per utente, un logo per azienda, un PDF per documento. Usare Spatie MediaLibrary significava:

  • Aggiungere una migrazione e una nuova tabella
  • Scrivere collection configuration per ogni modello
  • Accettare query extra per ogni operazione
  • Gestire complessità non necessaria per casi d'uso basilari

Mi sono chiesto: e se potessi semplicemente usare una colonna VARCHAR nel database e lasciare che il package si occupi del resto? Da questa domanda è nato Laravel Model Media.

L'obiettivo era chiaro: rendere la gestione dei media così semplice da essere indistinguibile dalla gestione di qualsiasi altro attributo del modello. Se puoi salvare una stringa in una colonna, puoi salvare un file con la stessa facilità.

Cosa Offre Laravel Model Media

Zero Configurazione Database

Non serve creare nuove tabelle. Usa le colonne che già hai o aggiungi una semplice colonna stringa alla tua migrazione esistente.

// Migrazione: aggiungi solo una colonna stringa
Schema::table('users', function (Blueprint $table) {
    $table->string('profile_photo')->nullable();
});

// Registra la colonna come media
self::registerMediaForColumn(
    column: 'profile_photo',
    directory: 'avatars',
    fileName: 'id'
);

Pulizia Automatica Completa

Laravel Model Media gestisce automaticamente la pulizia dei file. Quando carichi un nuovo file, quello vecchio viene eliminato. Quando elimini il modello, tutti i file associati vengono rimossi dal disco.

// Primo upload
$user->attachMedia($photo1, 'profile_photo');
// File salvato: storage/app/public/avatars/1.jpg

// Secondo upload: il vecchio file viene eliminato automaticamente
$user->attachMedia($photo2, 'profile_photo');
// File vecchio eliminato, nuovo file salvato

// Eliminazione modello: tutti i file associati vengono rimossi
$user->delete();
// Tutti i file del modello vengono cancellati dal disco

Naming Intelligente e Flessibile

Puoi nominare i file in base agli attributi del modello o usare una Closure per logiche più complesse.

// Nome file basato su attributo
self::registerMediaForColumn(
    column: 'avatar',
    directory: 'avatars',
    fileName: 'id'  // Usa l'ID del modello
);
// Risultato: avatars/123.jpg

// Nome file dinamico con Closure
self::registerMediaForColumn(
    column: 'invoice_pdf',
    directory: 'invoices',
    fileName: fn ($model, $file) => "invoice-{$model->number}-" . Str::random(5)
);
// Risultato: invoices/invoice-INV-001-x7kP2.pdf

Supporto Multi-Disk

Gestisci file su diversi storage disk senza complicazioni. Avatar su disco pubblico, documenti sensibili su S3.

// Avatar pubblici
self::registerMediaForColumn(
    column: 'avatar',
    directory: 'avatars',
    fileName: 'id',
    disk: 'public'
);

// Contratti privati su S3
self::registerMediaForColumn(
    column: 'contract',
    directory: 'contracts',
    fileName: 'id',
    disk: 's3'
);

Manipolazione Immagini con Glide

La versione 2.0 introduce il supporto completo a Glide per la manipolazione on-the-fly delle immagini. Ridimensiona, ritaglia, converti formati e genera immagini responsive senza preprocessing.

// Ridimensiona a 200x200
$url = $user->getGlideUrl('avatar', ['w' => 200, 'h' => 200]);

// Converti in WebP con qualità personalizzata
$url = $user->getGlideUrl('avatar', ['fm' => 'webp', 'q' => 85]);

// Ritaglia al centro
$url = $user->getGlideUrl('avatar', [
    'w' => 300,
    'h' => 300,
    'fit' => 'crop'
]);

Preset per Immagini

Definisci preset riutilizzabili per trasformazioni comuni.

// config/model-media-glide.php
'presets' => [
    'thumbnail' => [
        'w' => 200,
        'h' => 200,
        'fit' => 'crop',
        'fm' => 'webp',
        'q' => 90,
    ],
    'og-image' => [
        'w' => 1200,
        'h' => 630,
        'fit' => 'crop',
        'fm' => 'jpg',
        'q' => 85,
    ],
],

// Usa i preset nel codice
$thumbnailUrl = $user->getGlidePresetUrl('avatar', 'thumbnail');
$ogImageUrl = $post->getGlidePresetUrl('cover', 'og-image');

Immagini Responsive

Genera automaticamente srcset per immagini responsive.

// Genera srcset con larghezze personalizzate
$srcset = $post->getGlideSrcset('cover', [375, 768, 1024, 1920]);

// Usa nel template
<picture>
    <source 
        srcset="{{ $post->getGlideSrcset('cover') }}"
        sizes="(max-width: 768px) 100vw, 800px"
    >
    <img 
        src="{{ $post->getGlideUrl('cover', ['w' => 800]) }}"
        alt="{{ $post->title }}"
        loading="lazy"
    >
</picture>

Validazione Automatica Tipi

Il trait HasGlideUrls valida automaticamente che i file siano immagini prima di generare URL di trasformazione.

// Valida automaticamente il tipo
if ($user->hasImageMedia('avatar')) {
    $url = $user->getGlideUrl('avatar', ['w' => 200]);
} else {
    // Mostra placeholder o file icon
}

// Oppure gestisci errori esplicitamente
try {
    $url = $user->getGlideUrl('document', ['w' => 200], throwOnError: true);
} catch (InvalidMediaTypeException $e) {
    // Il file non è un'immagine
}

Cache Automatica Glide

Glide genera versioni trasformate delle immagini e le mantiene in cache. Laravel Model Media gestisce automaticamente la pulizia della cache quando:

  • Carichi una nuova immagine (vecchie versioni cached vengono eliminate)
  • Elimini il modello (tutte le versioni cached vengono rimosse)

Tutto questo avviene in background tramite un observer dedicato.

Installazione Rapida

composer require dialloibrahima/laravel-model-media

Per la manipolazione immagini, installa Glide:

composer require league/glide

Aggiungi i trait al modello:

use DialloIbrahima\HasMedia\HasMedia;
use DialloIbrahima\HasMedia\Plugins\Glide\HasGlideUrls;

class User extends Model
{
    use HasMedia, HasGlideUrls;

    protected static function booted()
    {
        self::registerMediaForColumn(
            column: 'profile_photo',
            directory: 'avatars',
            fileName: 'id'
        );
    }
}

E inizia subito:

// Upload
$user->attachMedia($request->file('photo'), 'profile_photo');

// Recupera URL
$url = $user->getMediaUrl('profile_photo');

// Con trasformazione
$thumbnail = $user->getGlideUrl('profile_photo', ['w' => 200, 'h' => 200]);

Quando Usare Laravel Model Media

Laravel Model Media è perfetto per casi d'uso diretti e comuni:

  • Avatar e foto profilo: un file per utente, nessuna collezione complessa
  • Loghi aziendali: un'immagine per organizzazione
  • Documenti singoli: PDF, contratti, certificati associati a un record
  • Immagini di copertina: blog post, prodotti, articoli
  • File allegati semplici: dove non serve gestire gallerie o collezioni multiple

Quando NON usarlo:

  • Gallerie fotografiche con decine di immagini per record
  • CMS complessi con conversioni multiple e collezioni annidate
  • Sistemi che richiedono metadati estesi su ogni file (titolo, descrizione, copyright)

Per questi casi, Spatie MediaLibrary rimane la scelta migliore. Laravel Model Media risolve il 90% dei casi d'uso con il 10% della complessità.

Confronto: Spatie vs Laravel Model Media

Caratteristica Spatie MediaLibrary Laravel Model Media
Filosofia "Una tabella per tutto" "Mantienilo sul modello"
Tabelle extra media (Polymorphic) Nessuna
Complessità Alta (Conversions, Collections) Bassa (Semplice e veloce)
Performance Query extra per ogni file Zero query extra
Setup Migrations + Trait + Interface Solo trait
Manipolazione immagini Conversioni built-in Plugin Glide (opzionale)
Ideale per CMS complessi, gallerie multiple Avatar, documenti singoli, upload semplici

Open Source e Testato

Laravel Model Media è completamente open source con licenza MIT. Include una suite di test completa che garantisce:

  • Corretta generazione di path e filename
  • Eliminazione automatica di file obsoleti
  • Garbage collection durante l'eliminazione del modello
  • Generazione URL Glide e trasformazioni
  • Validazione tipi di file per immagini
  • Gestione errori per file non-immagine

Il progetto è ospitato su GitHub dove puoi contribuire, segnalare bug o suggerire funzionalità: https://github.com/ibra379/laravel-model-media

Roadmap

La versione 2.0 introduce il plugin Glide per la manipolazione immagini. Il futuro include:

  • Cache warming: pre-generazione di preset comuni
  • Eventi personalizzati: hook per cache hit/miss e trasformazioni
  • Supporto video: conversione e thumbnailing automatico
  • Integration kit: helper per integrazioni comuni (Livewire, Inertia)

L'obiettivo principale rimane invariato: mantenere il package semplice, leggero e facile da usare senza sacrificare funzionalità essenziali.

Conclusione

Laravel Model Media nasce dalla convinzione che la maggior parte delle applicazioni non ha bisogno di una libreria media complessa. Se il tuo caso d'uso è semplice, la soluzione dovrebbe essere altrettanto semplice.

Usa le colonne che già hai. Aggiungi un trait. Carica file. Tutto il resto è automatico: pulizia, URL generation, trasformazioni immagini, cache management.

Provalo oggi e scopri quanto può essere semplice gestire media in Laravel senza compromessi sulla qualità del codice.

⭐ Se trovi utile questo package, lascia una stella su GitHub!