Often you want to be able to assign some media to your Eloquent models.
Craftable provides you an option to do that. It uses Spatie's spatie/laravel-medialibrary
, but it goes a bit further:
There are two core concepts to understand - MediaCollections
and MediaConversions
.
If you have different types of files that you want to associate with your model (e.g. image gallery, list of PDFs), you can put them in their own MediaCollection
.
When adding files to your media library, MediaConversions
can automatically create derived versions such as thumbnails, optimized versions, etc.. You can register as many MediaConversions
as you want.
First, we need to define the media collections for the specific model.
Let's imagine a Post
model for following examples. You need to register media collection like this:
use Illuminate\Database\Eloquent\Model;
use Brackets\Media\HasMedia\ProcessMediaTrait;
use Brackets\Media\HasMedia\AutoProcessMediaTrait;
use Brackets\Media\HasMedia\HasMediaCollectionsTrait;
use Spatie\MediaLibrary\HasMedia\HasMedia;
class Post extends Model implements HasMedia {
use ProcessMediaTrait;
use AutoProcessMediaTrait;
use HasMediaCollectionsTrait;
public function registerMediaCollections() {
$this->addMediaCollection('gallery');
}
Here we have added new gallery
media collection.
If we use AutoProcessMediaTrait
media are attached automatically from the request (on saving
event hook). You just need to use our uploader element or attach a gallery
data structure to your request data like this:
class PostsController extends Controller {
...
public function store(StoreRequest $request)
{
// this will automatically attach $request->file('gallery') to the Post
$post = Post::create($request->validated());
...
}
The $request->gallery
should be an array in following format:
[
[
'id' => null,
'collection_name' => 'gallery',
'path' => 'my_lovely_picture_1.jpg',
'action' => 'add',
'meta_data' => [ // or any other data
'name' => 'test',
'width' => 200,
'height' => 200,
],
],
[
'id' => null,
'collection_name' => 'gallery',
'path' => 'my_lovely_picture_2.jpg',
'action' => 'add',
'meta_data' => [ // or any other data
'name' => 'test',
'width' => 200,
'height' => 200,
],
],
...
];
If Auto Process is not convenient it can be turned off simply by not using AutoProcessMediaTrait
.
Once turned-off you can still process media manually using processMedia()
method on your model or you can use Spatie's way of attaching media (see https://docs.spatie.be/laravel-medialibrary/v7/basic-usage/associating-files).
If you want to adjust media during handling (e.g. resize, crop, optimize, fine tune colors) you can do it by using Spatie's method registerMediaConversions
as shown below.
use Illuminate\Database\Eloquent\Model;
use Brackets\Media\HasMedia\ProcessMediaTrait;
use Brackets\Media\HasMedia\AutoProcessMediaTrait;
use Brackets\Media\HasMedia\HasMediaCollectionsTrait;
use Spatie\MediaLibrary\Models\Media;
use Spatie\MediaLibrary\HasMedia\HasMedia;
class Post extends Model implements HasMedia {
use ProcessMediaTrait;
use AutoProcessMediaTrait;
use HasMediaCollectionsTrait;
public function registerMediaCollections()
{
$this->addMediaCollection('gallery');
}
public function registerMediaConversions(Media $media = null)
{
$this->addMediaConversion('detail_hd')
->width(1920)
->height(1080)
->performOnCollections('gallery');
}
It uses Spatie's fluent API, so for more info, check out their docs at https://docs.spatie.be/laravel-medialibrary/v7/converting-images/defining-conversions.
To use our uploader/viewer UI component, first you must define media collections in your resources/js/admin/post/Form.js
:
import AppForm from '../app-components/Form/AppForm';
Vue.component('post-form', {
mixins: [AppForm],
data: function() {
return {
form: {
//your regular form inputs
title: this.getLocalizedFormDefaults(),
perex: this.getLocalizedFormDefaults()
},
mediaCollections: ['gallery']
}
}
});
Now in your form blades you can use brackets/admin-ui::admin.includes.media-uploader
blade component:
@include('brackets/admin-ui::admin.includes.media-uploader', [
'mediaCollection' => app(App\Models\Post::class)->getMediaCollection('gallery'),
'label' => 'Gallery'
])
You can also add media
key in your edit form to preview the attached media directly in your form. We recommend use it with our handy trait Brackets\Media\HasMedia\HasMediaThumbsTrait
in your Eloquent model:
<?php namespace App\Models;
...
use Brackets\Media\HasMedia\HasMediaThumbsTrait;
class Post extends Model implements HasMedia
{
use ProcessMediaTrait;
use AutoProcessMediaTrait;
use HasMediaCollectionsTrait;
use HasMediaThumbsTrait;
...
public function registerMediaCollections() {
$this->addMediaCollection('gallery')
->accepts('image/*')
->maxNumberOfFiles(20);
}
public function registerMediaConversions(Media $media = null)
{
$this->autoRegisterThumb200();
}
...
}
and in your form:
@include('brackets/admin-ui::admin.includes.media-uploader', [
'mediaCollection' => app(App\Models\Post::class)->getMediaCollection('gallery'),
'media' => $post->getThumbs200ForCollection('gallery'),
'label' => 'Gallery'
])
To retrieve files you can use the getMedia
method:
$mediaItems = $post->getMedia('nameOfTheCollection');
$publicUrl = $mediaItems[0]->getUrl();
// to retrieve media from any Media Conversion
$publicUrl = $mediaItems[0]->getUrl('nameOfTheConversion');
For more info check the Spatie's docs: https://docs.spatie.be/laravel-medialibrary/v7/basic-usage/retrieving-media
There are following methods on Media Collections
:
public function registerMediaCollections()
{
$this->addMediaCollection('gallery')
->disk('media') // Specify a disk where to store this collection
->private() // Alias to setting default private disk
->maxNumberOfFiles(10) // Set the file count limit
->maxFilesize(2*1024*1024) // Set the file size limit
->accepts('image/*') // Set the accepted file types (in MIME type format)
->canView('media.view') // Set the ability (Gate) which is required to view the medium (in most cases you would want to call private())
->canUpload('media.upload') // Set the ability (Gate) which is required to upload & attach new files to the model
}