Media
The core adds a Media library at /admin/media, for every role. A file is uploaded once, several at a time if needed, and can then be used by any record of the site. Each file has a name and, for an image, an alternative text per site language.
Every file is a record of the library. A field that takes a file saves the id of a record, never a path.
Image sizes
Every image gets these sizes at upload, as WebP files next to the original:
| Size | Result |
|---|---|
thumb | 400 × 400, cropped to fill the square |
medium | 800 wide, same proportions |
large | 1600 wide, same proportions |
An image is never enlarged, and the original is kept as uploaded. Animated GIFs, PDFs and other documents keep the original only.
An upload never fails because of a size. An image too large to resize within PHP's memory_limit with GD (about 15 bytes per pixel: a 24-megapixel photo needs about 360 MB) keeps the original only. The error is written to the log.
The sizes are made in the upload request, not on a queue, because shared hosting often has no queue worker.
Giving a model an image
Add a nullable foreign key to the mela_media table for one image, or a JSON list of ids for a gallery:
// Migration
$table->foreignId('cover_id')->nullable()->constrained('mela_media')->nullOnDelete();
$table->json('gallery')->nullable();use Melasistema\MelaCms\Models\Media;
class Article extends Model
{
protected function casts(): array
{
return ['gallery' => 'array'];
}
public function cover(): BelongsTo
{
return $this->belongsTo(Media::class, 'cover_id');
}
public function galleryMedia(): Collection
{
return Media::inOrder($this->gallery); // skips a file that was deleted
}
}In the Filament form, MediaPicker picks a file from the library, or uploads a new one into it:
use Melasistema\MelaCms\Filament\Forms\MediaPicker;
MediaPicker::make('cover_id')->images(), // saves the id of the file
MediaPicker::make('gallery')->images()->multiple(), // saves a list of idsimages() limits the field to images. MediaPicker extends Filament's Select, so required(), label() and the rest work as usual.
In a view
@if ($article->cover)
<img
src="{{ $article->cover->url('large') }}"
srcset="{{ $article->cover->srcset() }}"
sizes="(min-width: 1024px) 800px, 100vw"
width="{{ $article->cover->width }}"
height="{{ $article->cover->height }}"
alt="{{ $article->cover->alt }}"
>
@endif| Method | Returns |
|---|---|
url() | The address of the original file |
url('thumb') | The address of a size. A file without that size gives the original |
srcset() | The sizes that keep the proportions, for the srcset attribute. null when there are none |
alt | The alternative text in the language of the request, with the default language as fallback |
width, height | The size of the original image |
isImage() | Whether the file is an image |
Eager-load the relation in lists, for example Article::with('cover').
Configuration
// config/mela-cms.php
'media' => [
'disk' => 'public',
'directory' => 'media',
'max_size' => 10240, // kilobytes
'accepted_types' => ['image/jpeg', 'image/png', 'image/webp', 'image/gif', 'application/pdf'],
'conversions' => [
'thumb' => ['width' => 400, 'height' => 400],
'medium' => ['width' => 800],
'large' => ['width' => 1600],
],
'quality' => 80,
],A size with a width and a height is cropped to fill them. A size with only one of the two keeps its proportions. After changing conversions or quality, make the sizes of the files already uploaded again:
php artisan mela:media-regenerateThe disk must be public. With the default disk the files are served through the public/storage link, which mela:install, mela:update and the deploy create. PHP's upload_max_filesize and post_max_size must allow max_size, and Livewire has its own limit of 12 MB per upload.
SVG
SVG is not accepted by default. An SVG file can carry a script, and it would run on your domain. Add image/svg+xml to accepted_types only if everyone who can log in is trusted.
Changing the screen
Extend Melasistema\MelaCms\Filament\Resources\Media\MediaResource, override formComponents() or tableColumns(), and set your class as resources.media in the config. To change who may use the library, register your own policy for Media with Gate::policy().
Known limits
- The library does not show where a file is used before you delete it.
- A gallery cannot be reordered by dragging.
- The file of a record cannot be replaced.
- There are no folders or tags.