Laravel-medialibrary v7 preview: media collections
laravel-medialibrary is a package that can help handle media in a Laravel application. It can organise your files across multiple filesystems, generate thumbnails, optimize images and much much more.
Like mentioned before on this blog my team and I are currently creating a new major version, v7, that adds a lot of awesome features such as responsive images, vue components to assist with uploading, ... Last week you got a preview of multi file downloads, ... This week we are going to look at some improvements to defining media collections.
What are media collections?
Media collections already exist in the current version of the medialibrary. They allow you to put different types of files in their own collection.
Let's associate some media:
$newsItem = News::find(1);
$newsItem->addMedia($pathToImage)->toMediaCollection('images');
$newsItem->addMedia($pathToAnotherImage)->toMediaCollection('images');
$newsItem->addMedia($pathToPdfFile)->toMediaCollection('downloads');
$newsItem->addMedia($pathToAnExcelFile)->toMediaCollection('downloads');
All media in a specific collection can be retrieved like this:
// will return media instances for all files in the images collection
$newsItem->getMedia('images');
// will returns media instance for all files in the downloads collection
$newsItem->getMedia('downloads');
New functionalities in v7
In v7 a media collection can be more than just a name to group files. By defining a media collection in your model you can add certain behaviours to collections.
To get started with media collections add a function called registerMediaCollections
to your prepared model. Inside that function you can use addMediaCollection
to start a media collection.
// in your model
public function registerMediaCollections()
{
$this->addMediaCollection('my-collection')
//add options
...
// you can define as much collections as needed
$this->addMediaCollection('my-other-collection')
//add options
...
}
Only allow certain files in a collection
You can pass a callback to acceptsFile
that will check if a file is allowed into the collection. In this example we only accept jpeg
files:
use Spatie\MediaLibrary\File;
...
public function registerMediaCollections()
{
$this
->addMediaCollection('only-jpegs-please')
->acceptsFile(function (File $file) {
return $file->mimeType === 'image/jpeg';
});
}
This will succeed:
$yourModel->addMedia('beautiful.jpg')->toMediaCollection('only-jpegs-please');
This will throw a Spatie\MediaLibrary\Exceptions\FileCannotBeAdded\FileUnacceptableForCollection
exception:
$yourModel->addMedia('ugly.ppt')->toMediaCollection('only-jpegs-please');
Using a specific disk
You can ensure that files added to a collection are automatically added to a certain disk.
// in your model
public function registerMediaCollections()
{
$this
->addMediaCollection('big-files')
->useDisk('s3');
}
When adding a file to my-collection
it will be stored on the s3
disk.
$yourModel->addMedia($pathToFile)->toMediaCollection('big-files');
You can still specify the disk name manually when adding media. In this example the file will be stored on alternative-disk
instead of s3
.
$yourModel->addMedia($pathToFile)->toMediaCollection('big-files', 'alternative-disk');
Single file collections
If you want a collection to hold only one file you can use singleFile
on the collection. A good use case for this would be an avatar collection on a User
model. In most cases you'd want to have a user to only have one avatar
.
// in your model
public function registerMediaCollections()
{
$this
->addMediaCollection('avatar')
->singleFile();
}
The first time you add a file to the collection it will be stored as usual.
$yourModel->add($pathToImage)->toMediaCollection('avatar');
$yourModel->getMedia('avatar')->count(); // returns 1
$yourModel->getFirstUrl('avatar'); // will return an url to the `$pathToImage` file
When adding another file to a single file collection the first one will be deleted.
// this will remove other files in the collection
$yourModel->add($anotherPathToImage)->toMediaCollection('avatar');
$yourModel->getMedia('avatar')->count(); // returns 1
$yourModel->getFirstUrl('avatar'); // will return an url to the `$anotherPathToImage` file
Registering media conversions
It's recommended that your first read the section on converting images before reading the following paragraphs.
Normally image conversions are registered inside the registerMediaConversions
function on your model. However, images conversions can also be registered inside media collections.
public function registerMediaCollections()
{
$this
->addMediaCollection('my-collection')
->registerMediaConversions(function (Media $media) {
$this
->addMediaConversion('thumb')
->width(100)
->height(100);
});
}
When adding an image to my-collection
a thumbnail that fits inside 100x100 will be created.
$yourModel->add($pathToImage)->toMediaCollection('my-collection');
$yourModel->getFirstMediaUrl('thumb') // returns an url to a 100x100 version of the added image.
Take a look at the defining conversions section to learn all the functions you can tack on to addMediaConversion
.
In closing
These improvements are coming to v7 of laravel-medialibrary. v7 will probably be released around February - March 2018. Of course you can start using v6 of laravel-medialibrary right now.
What are your thoughts on "Laravel-medialibrary v7 preview: media collections"?