Oh Dear! monitors your entire website, not just the homepage. You'll get a notification as soon as your website is down, a monthly uptime report, a warning a few days before your SSL certificate expires and much more! Start your free 10 day trial now!

Laravel-medialibrary v7 preview: media collections

Original – by Freek Van der Herten – 5 minute read

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.

Stay up to date with all things Laravel, PHP, and JavaScript.

Every two weeks I send out a newsletter containing lots of interesting stuff for the modern PHP developer.

Expect quick tips & tricks, interesting tutorials, opinions and packages. Because I work with Laravel every day there is an emphasis on that framework.

Rest assured that I will only use your email address to send you the newsletter and will not use it for any other purposes.