sertxudeveloper/laravel-media-model
Laravel Media Model adds straightforward media handling to Eloquent models, letting you attach images and files to records through a dedicated Media model and reusable relationships. Store uploads and retrieve associated media alongside your model data.
sertxudeveloper/laravel-media-model is a model-media attachment package for Laravel. v1.3.0 is primarily a maintenance release: it adds Laravel 11.x support and updates CI/dependency automation. No documented API-breaking changes are called out, but verify the package’s composer.json constraints before upgrading in a mixed PHP/Laravel fleet.
Minimal adoption path:
composer require sertxudeveloper/laravel-media-model
php artisan vendor:publish --provider="Sertxudeveloper\\MediaModel\\MediaModelServiceProvider"
php artisan migrate
php artisan storage:link
use Sertxudeveloper\MediaModel\Traits\HasMedia;
class User extends Authenticatable
{
use HasMedia;
}
Confirm the exact trait namespace in the installed package/README.User, store it on a configured disk, and render its URL on a profile page. Start with one model and one media type before wiring it into every resource.Where to look first:
README.md for current attach/retrieve/delete APIs.composer.json for Laravel 11 and PHP compatibility.config/media-model.php or equivalent for disk, path, and model settings.Single-file upload from a form request
Validate the upload in a Form Request, authorize ownership, then hand the validated file to the package attach API. Keep controller code thin:
$validated = $request->validated();
$user->addMedia($validated['avatar'])
->toMediaCollection('avatar');
Use the package’s actual attach method names from the README. The important pattern is: validate first, authorize second, persist third, and only then generate URLs.
Retrieval in Blade/API resources
Eager load the media relation before rendering lists to avoid N+1 queries:
$users = User::with('media')->paginate();
Then expose a stable field in API resources:
'avatar_url' => $user->getFirstMediaUrl('avatar') ?: asset('images/avatar-placeholder.png'),
Centralize fallback URLs and URL generation so views/API consumers do not depend directly on storage paths.
Model lifecycle and cleanup
Treat media as part of the model lifecycle. Delete DB rows and storage files together where possible. If the package does not cascade automatically, add a model observer or explicit service method:
$user->delete(); // ensure media records/files are cleaned up
For soft-deleting models, decide whether media should remain, be hidden, or be purged later. Document that behavior.
Collections and multiple media types
Use named collections/directories for avatars, documents, galleries, etc. This keeps retrieval predictable:
$user->addMedia($request->file('avatar'))->toMediaCollection('avatar');
$user->addMedia($request->file('contract'))->toMediaCollection('documents');
If the package supports conversions/thumbnails, keep conversion definitions close to the media model or a dedicated configuration class rather than scattering them across controllers.
Integration with policies and API resources
Authorize media access at the model level. Do not rely on an unguessable URL as authorization. For private disks, use temporary URLs or a controller endpoint that checks a policy before streaming the file. For public avatars, public disk URLs are fine.
Upgrade workflow for Laravel 11
Because v1.3.0 adds Laravel 11 support, test the upgrade in a branch:
composer update sertxudeveloper/laravel-media-model --with-dependencies
php artisan config:clear
php artisan migrate
php artisan test
Check that service provider auto-discovery, config publishing, and migration tags still work under Laravel 11.
composer.json for PHP/Laravel constraint changes.php artisan config:clear and re-cache in deployment.storage:link in every environment that serves public media through the web server. Missing symlinks are a common “file exists but 404s” cause.$model->getFirstMediaUrl() inside a loop without eager loading can produce N+1 queries.vendor/ directly.config/filesystems.php, check storage/logs/laravel.log, confirm the published migration ran, confirm the model uses the trait, clear config/cache, and test both URL generation and direct file existence.How can I help you explore Laravel packages today?