Top 5 Questions/Answers About Spatie MediaLibrary
Founder of QuickAdminPanel
Inside of our QuickAdminPanel generator, we use Spatie MediaLibrary package for file uploads. And our customers often ask as questions about it, so we decided to compile the most popular ones and answer them in one article. It can be useful for any Medialibrary user, even without QuickAdminPanel.
Question 1. Where are my files stored?
This question may be very simple, and also may be very complicated. Cause there are at least three configuration files where you can set this preference:
- config/medialibrary.php
- config/filesystems.php
- .env
By default, config/medialibrary.php doesn’t exist. It is created only if you run this command from the package installation tutorial:
php artisan vendor:publish --provider="Spatie\MediaLibrary\MediaLibraryServiceProvider" --tag="config"
But even if we don’t have this config file published, the package still takes the default values from it’s core code in the /vendor folder. So let’s take a look at these default values.
Again, from their documentation – this is the default content of the config file (will skip the parameters irrelevant to this article):
return [ /* * The filesystems on which to store added files and derived images by default. Choose * one or more of the filesystems you've configured in config/filesystems.php. */ 'disk_name' => 'public', /* * The class that contains the strategy for determining a media file's path. */ 'path_generator' => null, 's3' => [ /* * The domain that should be prepended when generating urls. */ 'domain' => 'https://xxxxxxx.s3.amazonaws.com', ], /* * The path where to store temporary files while performing image conversions. * If set to null, storage_path('medialibrary/temp') will be used. */ 'temporary_directory_path' => null, ];
In fact, we’re mostly interested in one main parameter ‘disk_name’, and by default it’s set to ‘public’.
Now, what does that mean?
It refers to public disk in config/filesystems.php:
'disks' => [ 'local' => [ 'driver' => 'local', 'root' => storage_path('app'), ], 'public' => [ 'driver' => 'local', 'root' => storage_path('app/public'), 'url' => env('APP_URL').'/storage', 'visibility' => 'public', ], 's3' => [ // ...
In other words, default MediaLibrary stores files in storage/app/public folder, creating subfolders inside for each Media entry:
If you want to change that location, you have multiple options:
- Change config/filesystems.php file’s public disk parameters to some other folders, for example ‘root’ => public_path(‘uploads’),;
- Publish Medialibrary config with the command mentioned above, and change config/medialibrary.php disk_name from ‘public’ to whatever other disk you want;
- Add some variables to .env file and use env() function in config files, so every teammate/server would have different folders for upload.
You can read more about file storage in our other popular article:
File Upload in Laravel: The Ultimate Guide
Question 2. Why are my files not shown? 404 error?
Partly related to the first question about file storage and how it works, not only in Medialibrary, but generally in Laravel.
By default, if you store file XXXXX.jpg in storage/app/public, you should be able to access it with URL /storage/XXXXX.jpg. But there’s a catch – first time trying to load it, will give you a 404 error:
That’s actually a good thing – the whole purpose of /storage folder is to save files to NOT be available to public by default, so it’s a security protection.
To make it work for public disk, you need to run this command, as described in the official Laravel documentation:
php artisan storage:link
It creates a symlink file in /public folder, which tells the operating system that URL /storage/XXXXX.jpg should be actually taken from /storage/app/public/XXXXX.jpg.
Question 3. How to generate/customize thumbnails?
This is a question I’ve answered already in this YouTube video:
But answering in text format, it’s a very simple solution – in your Model you need to add a method registerMediaConversions().
For example, you want to add 50×50 thumbnails to every upload for User model. So you add this to app/User.php:
use Spatie\MediaLibrary\Models\Media; // ... public function registerMediaConversions(Media $media = null) { $this->addMediaConversion('thumb')->width(50)->height(50); }
And then you can call that thumbnail by the name assigned here, which is ‘thumb’:
$user = User::find(1); $mediaItems = $user->getMedia('images'); $mediaItems[0]->getUrl('thumb');
Question 4. How to query Media relationships in Eloquent?
Sometimes you need to retrieve media files along with your main model, in one Eloquent query.
Something, like… User::with(‘media’)->first();, but there’s no “media” as relationship. Should it be hasMany, or belongsToMany, or something else?
Medialibrary stores data in media database table with Polymorphic relationships. I also have a video on this topic:
So, to query the Media files for a User, we should add this to app/User.php:
use Spatie\MediaLibrary\Models\Media; class User extends Model implements HasMedia { /** * Get all of the user's images. */ public function media() { return $this->morphMany(Media::class, 'model'); }
That ‘model’ part refers to two fields: media.model_id and media.model_type.
And now, we can do exactly the thing posted above:
$user = User::with('media')->find(1); foreach ($user->media as $mediaFile) { // ...
Question 5. Why artisan migrate doesn’t work with MediaLibrary?
Probably the most often question asked by our customers. When they run the migrations, generated by our QuickAdminPanel, this error sometimes appears:
The answer here is pretty simple – here’s a quote from the Requirements section:
This package uses ‘json’ columns. MySQL 5.7 or higher is required.
So no way around it, you have to upgrade MySQL version, or switch from MariaDB (or other DB you’re using) to MySQL 5.7+.
There are problems with some web-server packages like XAMPP that switch on MariaDB by default, so check their documentation how to turn it off.
These were the most typical questions about Medialibrary, but you can also read its official documentation, it’s pretty well written.