This package allows you to give your users a beautiful way to upload images to your application and manage their library. It integrates with and is based on Spatie MediaLibrary, one of the most popular and widely used packages in the Laravel ecosystem.
New: Package includes Filament V3 support!
Upgrading from V1 to V2?
Upgrading from V2 to V3?
The MediaLibrary page is the page where your users can view all their images. The complete package is compatible with both dark- and lightmode.
Users can drag-and-drop their images unto the upload component. Bulk uploads are allowed. You can use Laravel's queue processing feature to handle the process of generating responsive images in the background.
You can use the MediaPicker Field everywhere inside the admin panel where you want it: as a single field or in a repeater. It works everywhere.
When a user clicks on 'Choose image', he/she will see the following modal, which they can use to pick an image.
Users can also pick multiple images at the same time (V2-feature):
You can browse images using the UI:
For each image, you can view the image, view rows of information (can add custom rows) and edit each item using a custom form:
One of the use cases could be to allow adding tags to images:
By default Filament comes with its own CSS, which integrates neatly into the admin panel design. However, as I did in the above screenshots, it is just as beautiful if you integrate it with your own Filament theme.
Thank you for purchasing the ultimate Media Library plugin for Filament Admin!
We tried to make the library as easy-to-install and versatile as possible. Nevertheless, if you still have a question or a feature request, please send an e-mail to support@ralphjsmit.com.
In this guide I'll show you how to install the library, so you can start using it right away.
For these installation instructions to work, you'll need to have the Filament package installed and configured.
The package makes use of the Spatie MediaLibrary package. If you already have this package installed, you can skip this step.
We'll need to publish the required migration first by running the following Artisan command.
php artisan vendor:publish --provider="Spatie\MediaLibrary\MediaLibraryServiceProvider" --tag="medialibrary-migrations"
The package is supported on Laravel 10 and 11 (with earlier versions available since Laravel 8). Please be aware though that support for security fixes for Laravel 10 ends within a few months.
You'll also need to have the ImageMagick PHP-extension installed on your system for the image conversions to happen. This is a relatively common extension and required by the underlying Spatie media library plugin. If you are using Laravel Sail, check out the section below.
If you use Laravel Sail, installing ImageMagick requires a few additional steps. To get started, try the following steps:
php artisan sail:publish
to publish your DockerFiles.docker/8.1/docker/Dockerfile
for PHP 8.1).php8.1-imagick
to the line with the PHP extensions (use the correct PHP version).php artisan sail build --no-cache
.To install the package you should add the following lines to your composer.json
file in the repositories
key in order to allow access to the private package:
{ "repositories": [ { "type": "composer", "url": "https://satis.ralphjsmit.com" } ]}
If you have one of my other premium packages installed already, then you don't need to repeat these lines.
Next, you should require the package via the command line. You will be prompted for your username (which is your e-mail) and your password (which is your license key, e.g. 8c21df8f-6273-4932-b4ba-8bcc723ef500
).
composer require ralphjsmit/laravel-filament-media-library
If you want to use the plugin in Filament V2, please require the '^2.0'
version. If you want to use the plugin in Filament V3, please require the '^3.0'
version (which is the default).
After purchasing the plugin, you'll also be shown installation instructions with the appropriate credentials pre-filled.
Finally, you'll need to publish the migration and migrate the database:
php artisan vendor:publish --tag="filament-media-library-migrations" # You can also publish the translations if wanted:php artisan vendor:publish --tag="filament-media-library-translations" php artisan migrate
tailwind.config.js
(required)Since this plugin registers new HTML, you need to make sure that the Tailwind CSS classes are generated. New in Filament V3 is that you need to create a custom theme in order to include CSS from plugins (in order to keep your panel as fast as possible). If you do not follow this step, you risk that the plugin pages/designs look weird, because CSS is missing.
First, make sure you are using a custom theme for every panel that you want to use the media library in. Please check that you registered your theme in your panel provider(s) using $panel->viteTheme('resources/css/filament/{nameOfTheme}/theme.css
)` for Vite or the method for Mix specified in the create theme command output.
Next, you'll need to instruct Tailwind to also purge the view-files for the media library. Add the following key to the content
key of the tailwind.config.js
file for each of the themes you use the media library in:
content: [ // Your other files './vendor/ralphjsmit/laravel-filament-media-library/resources/**/*.blade.php'],
NB. The
tailwind.config.js
you need to add this line to is not a possibletailwind.config.js
file in your root project, but only in theresources/css/filament/{nameOfTheme}/tailwind.config.js
file(s) of your theme(s).
If you are using the plugin in Filament V3, you should register the plugin in each of the panels that you have in your project and would like to use the media library in:
use RalphJSmit\Filament\MediaLibrary\FilamentMediaLibrary; $panel ->plugin(FilamentMediaLibrary::make())
In the rest of the below documentation, if we refer to the $plugin
variable, then we mean the $plugin = FilamentMediaLibrary::make()
. This is not necessarily a variable, but it helps to keep the code examples shorter and simpler.
Therefore, the following code examples mean the same:
$plugin ->diskVisibilityPrivate() ->someOtherMethod();
use RalphJSmit\Filament\MediaLibrary\FilamentMediaLibrary; $panel ->plugin( FilamentMediaLibrary::make() ->diskVisibilityPrivate() ->someOtherMethod() )
The Filament Media library uses the Spatie Medialibrary as underlying package. By default, the Spatie Medialibrary package will put your images on the public
disk.
If you want to change the disk, publish the Spatie Medialibrary configuration file and update the disk_name
value:
php artisan vendor:publish --provider="Spatie\MediaLibrary\MediaLibraryServiceProvider" --tag="medialibrary-config"
Then, configure the panel with your new disk in the config/media-library.php
. This could be an S3 disk for example.
/* * The disk on which to store added files and derived images by default. Choose * one or more of the disks you've configured in config/filesystems.php. */'disk_name' => env('MEDIA_DISK', 'public'),
Finally, if your disk is a private disk (like S3), then you need to update the filament-media-library.disk.visibility
value to “private”:
// By default, this package assumes that the disk you are using is public. If your disk// is private, use the below "diskVisibilityPrivate()" method to set it to "private".$plugin ->diskVisibilityPrivate() // Alternative: ->diskVisbility('private')
Finally, you'll also need to replace the default url_generator
in the config/media-library
to use the custom generator. This is only necessary if you have set your disk visibility to private:
/* * When urls to files get generated, this class will be called. Use the default * if your files are stored locally above the site root or on s3. */'url_generator' => RalphJSmit\Filament\MediaLibrary\UrlGenerator\MediaLibraryUrlGenerator::class,
If you skip this step, then you risk that some images in the library are not displayed correctly.
Using the media library is very simple. After installing it, you should see a new page in your sidebar called "Media library". On this page your users can upload images, view their other images, edit metadata and delete images.
It might be handy to know a bit about how the media library works under-the-hood. Each item in your media library is an instance of the RalphJSmit\Filament\MediaLibrary\Media\Models\MediaLibraryItem
Eloquent model. This model is used to store metadata about the image.
For example, if you have 10 images in your library, you will also have 10 MediaLibraryItem
models with metadata.
Adding an image can be done via the static addUpload
method on the MediaLibraryItem class. This method accepts an instance of Illuminate\Http\UploadedFile
.
use RalphJSmit\Filament\MediaLibrary\Media\Models\MediaLibraryItem; $uploadedFile = /** */; $mediaItem = MediaLibraryItem::addUpload($uploadedFile);
You only need to know the above information if you want to manually add uploaded files.
The image files itself are being stored by the Spatie MediaLibrary package. The files are stored in a collection called library
.
Sometimes you don't have an instance of an UploadedFile
ready, but you only have a path to the image. That situation is also possible, though it requires a little bit more work.
$path = /** */; $originalFileName = 'test.jpg'; $uploadedFile = UploadedFile::createFromBase(new \Symfony\Component\HttpFoundation\File\UploadedFile($path, $originalFileName)); MediaLibraryItem::addUpload($uploadedFile);
If you want to customize the navigation details of the Media library page, you can configure it using the dedicated methods on the $plugin
when configuring it:
$plugin ->navigationGroup('Media') ->navigationSort(1) ->navigationLabel('Media Browser') ->navigationIcon('heroicon-o-camera') ->activeNavigationIcon('heroicon-s-camera') ->pageTitle('Media Browser') ->slug('media-browser')
If you want to customise or override other aspects of the page, you can create a new class in your project that extends the \RalphJSmit\Filament\MediaLibrary\Media\Pages\MediaLibrary
page. In this class you can override everything you want to customize, like the title, navigation label or navigatin group.
Finally, you should register the new page in Filament by using the ->registerPages()
method:
$plugin->registerPages([ YourExtendedMediaLibraryPage::class,])
This plugin comes with a custom Filament field called a MediaPicker
. This field can be used to choose an image from the library. The field looks like this:
The field can be used anywhere you want: it behaves just like a normal field.
The field consists of two things:
Include the field like this:
use RalphJSmit\Filament\MediaLibrary\Forms\Components\MediaPicker; MediaPicker::make('image') ->label('Choose image') ->required(),
The value of the field will be the id
of the MediaLibraryItem that is being selected.
You can use the ->multiple()
to select multiple items using the MediaPicker component:
MediaPicker::make('images') ->label('Choose images') ->required() ->multiple(),
The value of the field will be an array with the id
's of the MediaLibraryItem's that are being selected.
You can limit the MediaPicker
to only allow selecting certain types of files. This works similar to the Filament FileUpload
field by exposing an ->acceptedFileTypes()
method.
For example, in order to only allow selecting PDFs, you can use it like this:
MediaPicker::make('brochure_id') ->label('Choose brochure') ->acceptedFileTypes(['application/pdf']),
The ->acceptedFileTypes()
function accepts the mimetypes of the files that you want to allow. You can use wildcards like video/*
or image/*
.
If you want to provide a custom validation message, you can use the ->validationMessages()
function:
MediaPicker::make('brochure_id') ->label('Choose brochure') ->acceptedFileTypes(['application/pdf']) // Optional, override custom validation message: ->validationMessages([ 'accepted_file_types' => 'Brochures can only be PDFs.', ])
If you want to require the user to select a minimum and/or maximum number of items, you can use the ->minFiles()
and ->maxFiles()
methods for that:
MediaPicker::make('brochure_ids') ->label('Choose brochures') ->minFiles(2) ->maxFiles(5) // Optional, override custom validation message: ->validationMessages([ 'min' => 'Please select at least 2 brochures.', 'max' => 'Please select maximum 5 brochures.', ])
By default, the MediaPicker will open in the root folder. However, in some cases, you might want to only allow your users to select/upload images from and to specific folders. You can do that using the ->folder()
function.
Forcing a specific folder do allow your users to create and select from sub-folder (e.g. go down in the hierarchy), but not to open up parent folders or go up in the hierarchy.
The folder()
functions accepts a MediaLibraryFolder
object as parameter. You can also pass a closure, and use that closure to retrieve the folder dynamically from e.g. the current record.
MediaPicker::make('featured_image_id') ->folder(MediaLibraryFolder::find(99)),
Using a closure:
MediaPicker::make('featured_image_id') ->folder(fn (Event $event) => $event->mediaLibraryFolder),
If you don't want to force your users to use a specific folder, but only nudge them, you can also use the ->defaultFolder()
method. This method allows you to specify a default folder that the MediaPicker will open in. The difference with ->folder()
is that this method will allow your users to open other folders as well, also higher in the hierarchy.
The defaultFolder()
functions accepts a MediaLibraryFolder
object as parameter. You can also pass a closure, and use that closure to retrieve the folder dynamically from e.g. the current record.
MediaPicker::make('featured_image_id') ->defaultFolder(MediaLibraryFolder::find(99)),
Using a closure:
MediaPicker::make('featured_image_id') ->defaultFolder(fn (Event $event) => $event->mediaLibraryFolder),
NB.: Please note that the media picker will now open this folder by default. However, users are still able to click to other folders and view them. If you have a need to disable this and only force a specific folder, please use the ->folder()
method (see above).
If you are allowing your users to select multiple items, you can use the ->reorderable()
method to allow your users to reorder the images. This can be useful in situations where the order of the media matters, for example if you want to construct a slideshow or carousel.
MediaPicker::make('images') ->label('Choose images') ->required() ->multiple() ->reorderable(),
The value of the field will be an array with the id
's of the MediaLibraryItem's that are being selected, in the order that they were selected.
If a user hovers over an image, the cursor will change into a “move” icon, so that it is clear that the media can be reordered.
If you want to allow users to have a convenient download button on selected items in the media picker, you can use the ->downloadable()
button:
MediaPicker::make('featured_image_id') ->label('Featured image') ->downloadable(),
By default, the MediaPicker will show nice previews/thumbnails for the selected items. However, if you are working with similar items that are hard to distinguish, you might want to display the file name of the selected items as well using the showFileName()
method:
MediaPicker::make('images') ->showFileName()
This will also display the file name of the selected items in the form. If you hover over the item name, then it will show the full path to the file.
The MediaPicker component will store the id
of the MediaLibraryItem
model. To display an image, you can use that id
to find the appropriate model.
Each model has a related Spatie\MediaLibrary\MediaCollections\Models\Media
model. You can use this Media
model to retrieve URLs, paths & other properties. You can use all the methods described in the Spatie MediaLibrary documentation.
$id = /** You stored this */ $mediaLibraryItem = MediaLibraryItem::find($id); $spatieMediaModel = $mediaLibraryItem->getItem(); $url = $spatieMediaModel->getUrl();$path = $spatieMediaModel->getPath(); //
We also provided support for the responsive images feature from Spatie. In order to display an <img>
tag with a responsive srcset
attribute, you can use the following:
{{ $mediaLibraryItem->getItem()->img('responsive') }}<!-- <img srcset="..." onload="..." sizes="..." src="..." width="..." height="..." alt="..."> -->
If you want to delete an image, please delete the MediaLibraryItem model and not Spatie's Media model. Spatie's Media model is automatically deleted when you delete the original MediaLibraryItem model.
By default, people can edit the caption and alt text of a media library item. If you want to add more fields or remove the default fields, you can do so by providing a callback to the MediaLibrary::registerMediaInfoFormFields()
-method in the boot()
method of a service provider.
This example will show you how to add a color picker to the form.
First, you need to create a migration to add the column in which we will save the hex-code:
Schema::table('filament_media_library', function(Blueprint $table) { $table->string('main_color')->nullable()->after('alt_text');});
use Filament\Forms\Components\ColorPicker;use RalphJSmit\Filament\MediaLibrary\Facades\MediaLibrary;use RalphJSmit\Filament\MediaLibrary\Media\Models\MediaLibraryItem; MediaLibrary::registerMediaInfoFormFields(function (array $schema, MediaLibraryItem $mediaLibraryItem): array { return array_merge($schema, [ ColorPicker::make('main_color') ->label('Main color'), ]);});
You can also remove the default fields by not merging them with the new fields:
MediaLibrary::registerMediaInfoFormFields(function (array $schema, MediaLibraryItem $mediaLibraryItem): array { return [ ColorPicker::make('main_color') ->label('Custom field'), ];});
If you want to hide all the fields, you can return an empty array:
Facades\MediaLibrary::registerMediaInfoFormFields(function (array $schema, MediaLibraryItem $mediaLibraryItem): array { return [];}, merge: false);
This example will show you how to add tags to your media library items based on the Filament Spatie Tags plugin. I will assume you have already run the migrations. You can find the installation instructions here.
Next, you need to prepare the Eloquent model for attaching tags. That means that we need to add a trait to the MediaLibraryItem Model. In order to achieve that, create a new file in your project with the name MediaLibraryItem
, that extends the original MediaLibraryItem
model and adds the HasTags
-trait. You could do this in your own app/Models
directory, but you are free to choose your own.
class MediaLibraryItem extends \RalphJSmit\Filament\MediaLibrary\Media\Models\MediaLibraryItem{ use HasTags;}
Then, register the tags input with the facade:
MediaLibrary::registerMediaInfoFormFields(fn (array $schema): array => [ ...$schema, SpatieTagsInput::make('tags'),]);
This is how the end-result will look like:
When viewing a media item in your library, you might notice that there are some extra rows of information displayed. You can overwrite the existing rows or add custom rows by providing a callback to the MediaLibrary::registerMediaInfoInformationUsing()
.
use RalphJSmit\Filament\MediaLibrary\Facades\MediaLibrary;use RalphJSmit\Filament\MediaLibrary\Media\DataTransferObjects\MediaItemMeta;use RalphJSmit\Filament\MediaLibrary\Media\Models\MediaLibraryItem; MediaLibrary::registerMediaInfoInformationUsing(function (array $information, MediaLibraryItem $mediaLibraryItem, MediaItemMeta $mediaItemMeta): array { return array_merge($information, [ 'ID' => $mediaLibraryItem->getKey(), 'Thumb conversion generated' => $mediaLibraryItem->getItem()->hasGeneratedConversion('thumb') ? 'Yes' : 'No', ]);});
The media library package offers support for policies. This allows you to determine whether a user can create a new media library item/folder or delete an old item/folder.
Supported checks for media library items are:
create
view
update
delete
First, create a policy (e.g. in app/Policies
) with the following contents:
<?php namespace App\Policies; class MediaLibraryItemPolicy{ public function create(User $user, ?MediaLibraryFolder $mediaLibraryFolder = null): bool { // `$mediaLibraryFolder` either `null` for the root-level or the current sub-folder in which to upload a new item. } public function view(User $user, MediaLibraryItem $mediaLibraryItem): bool { // } public function update(User $user, MediaLibraryItem $mediaLibraryItem): bool { // } public function replace(User $user, MediaLibraryItem $mediaLibraryItem): bool { // } public function regenerate(User $user, MediaLibraryItem $mediaLibraryItem): bool { // } public function delete(User $user, MediaLibraryItem $mediaLibraryItem): bool { // }}
Next, open up your AuthServiceProvider
and register the policy for the model:
protected $policies = [ MediaLibraryItem::class => MediaLibraryItemPolicy::class,];
Now you are ready and the create
and delete
actions are governed by a policy.
This will cause two new rows in the table to show up.
Supported checks for media library folders are:
create
view
update
delete
First, create a policy (e.g. in app/Policies
) with the following contents:
<?php namespace App\Policies; class MediaLibraryFolderPolicy{ public function create(User $user, ?MediaLibraryFolder $mediaLibraryFolder = null): bool { // `$mediaLibraryFolder` either `null` for the root-level or the current sub-folder in which to create a new folder. } public function view(User $user, MediaLibraryFolder $mediaLibraryFolder): bool { // } public function update(User $user, MediaLibraryFolder $mediaLibraryFolder): bool { // } public function delete(User $user, MediaLibraryFolder $mediaLibraryFolder): bool { // }}
Next, open up your AuthServiceProvider
and register the policy for the model:
protected $policies = [ MediaLibraryFolder::class => MediaLibraryFolderPolicy::class,];
Now you are ready and the create
and delete
actions are governed by a policy.
By default, the plugin registers four media conversions. The media conversions are:
responsive
small
(known as 400
)medium
(known as 800
)thumb
In case your media conversions are not being generated (or only the thumb
conversion), please ensure you have correctly set up a queue. The thumb
conversion will be generated directly when the user uploads an image (since it will be needed right-away to display the item), whereas the other conversions will be generated in the background on the queue in order to not unnecessarily slow down the upload so much. See also here.
You can modify these conversions using the following methods:
use Spatie\MediaLibrary\Conversions\Conversion; $plugin ->conversionResponsive(enabled: true, modifyUsing: function (Conversion $conversion) { // Apply any modifications you want to the conversion, or omit to use defaults... return $conversion->keepOriginalImageFormat(); }) ->conversionMedium(enabled: true, width: 800) ->conversionSmall(enabled: true, width: 400) ->conversionThumb(enabled: true, width: 600, height: 600)
If you disable the thumb
conversion, you should also update the ->thumbnailMediaConversion
and ->mediaPickerMediaConversion()
methods to use a different conversion:
// You can change the media conversion that is used to display the previews in the library.// The default conversion is `thumb`. This conversion is a square conversion and generated// automatically already. However, you can change the conversion to any other conversion.// Please keep in mind that square conversions that aren't large work best.$plugin ->thumbnailMediaConversion('thumb') ->mediaPickerMediaConversion('thumb'); // Same, but then for MediaPicker...
If you want to register additional media conversions, you can do so using the MediaLibrary::registerMediaConversions()
facade:
use RalphJSmit\Filament\MediaLibrary\Facades\MediaLibrary; MediaLibrary::registerMediaConversions(function (MediaLibraryItem $mediaLibraryItem, Media $media = null) { $mediaLibraryItem ->addMediaConversion('test'); // ..});
You should place the above code in the boot()
-method of a service provider. For example, the AppServiceProvider
or a custom provider, e.g. MediaLibraryServiceProvider
.
You are free to register as many conversions as you like. However, be aware that each new conversion takes up more disk space.
The media library also has support for uploading videos & PDFs. By default, these options are disabled, because they might need the installation of an addition library.
You can enable video and PDF-support using the plugin configuration:
// You can specify the filetypes you want your users to be able to upload.$plugin // There is no additional configuration needed for accepting images. ->acceptImage() // In order to upload PDFs, you need to have the "spatie/pdf-to-image" package configured correctly. // This package is already required via Composer, but you need to make sure that the extension for // imagick has been installed and that Ghostscript is installed. Check out the following link: // https://github.com/spatie/pdf-to-image#requirements ->acceptPdf() // In order to let your users upload videos, you need to have the FFmpeg binary installed. See // the website of FFmpeg for installation instructions: https://ffmpeg.org/download.html. ->acceptVideo()
You can update the width of the media picker modal using the ->mediaPickerModalWidth()
method in the plugin configuration. The default width is 7xl
.
$plugin->mediaPickerModalWidth('7xl');
It is possible to show the upload box by default instead of having to open the box first by clicking the 'upload' button. Depending on your application, this might improve the user experience.
To enable this behaviour, use the ->showUploadBoxByDefault()
on the plugin configuration:
$plugin->showUploadBoxByDefault();
When uploading files, it is required for the user to click the button "Store" in order to upload the files and push them to the server. The reason for this behaviour instead of auto-upload, is two-fold.
This can be confusing for some users. Some users forget to click "Store" and therefore the uploaded files never reach your server.
In order to solve this problem and improve the UX, you can choose to enable a warning box when there are files in the upload box that are not stored yet. The warning will be "Don't forget to click 'store' to upload your file/files".
To enable the warning box, set the ->unstoredUploadsWarning()
to true
:
$plugin->unstoredUploadsWarning();
If you open the MediaPicker to select an item from the library, you will see that the right hand side of the modal shows information about the current selected media item. If you open the MediaPicker to select multiple items from the library, then you won't see this information at the right by default. There is room to only show info about a single media item, so it could be confusing to show info about a single item when the selection is bigger.
However, an alternative approach could be to just allow multiple selection, and at the right show the details of the latest selected item. This type of behaviour is for example visible in the WordPress media library.
You can enable the alternative approach by using the ->mediaInfoOnMultipleSelection()
method:
$plugin ->mediaInfoOnMultipleSelection()
This will now show the details of the latest selected item at the right, even when selecting multiple items.
By default, the button of the media picker component will display "Choose image". You can override this by providing your own (dynamic) translation via the ->buttonLabel()
method:
MediaPicker::make('hero_image_id') ->buttonLabel('Choose hero image'),
You can use the MediaColumn to display a preview of the media item in a table resource. For this to work, you need to have a relationship to the media library item in your model.
For example, consider a situation where you have a thumbnail_id
on your Eloquent model. This thumbnail_id
will contain the ID of the media library item that has been selected using the MediaPicker::make('thumbnail_id')
. You then need to add the following relationship to your Eloquent model:
public function thumbnail(): BelongsTo{ return $this->belongsTo(MediaLibraryItem::class, 'thumbnail_id');}
Next, you can use the MediaColumn like this:
use RalphJSmit\Filament\MediaLibrary\Tables\Columns\MediaColumn; MediaColumn::make('thumbnail'),
All methods available on the ImageColumn
class are also available on the MediaColumn
class.
MediaColumn::make('thumbnail') ->circular() ->size(40)
You only do not need to use the ->collection()
, ->conversion()
methods.
If you are getting an error like
App\Models\Post::getMediaLibraryCollectionName()
, please check if the relationship is defined. For example, if you want to use athumbnail
relationship, check if there is a method calledthumbnail()
on your model that returns a relation.
You can also use the MediaColumn to display multiple images from a relationship. For example, consider that you have a Post
model with a thumbnail
relationship. Say that we also have an Author
model. We could add an HasManyThrough
relationship to the Author
model to get the thumbnails of the posts from this author:
class Author extends Model{ public function thumbnails(): HasManyThrough { return $this->hasManyThrough( MediaLibraryItem::class, Post::class, 'author_id', // Foreign key on posts table 'id', // Key on authors table 'id', // Key on filament_media_library_items table 'thumbnail_id', // Foreign key on posts table ); } // ...}
Next, we could use the MediaColumn to display the thumbnails of the posts from this author:
MediaColumn::make('thumbnails') ->circular() ->stacked()
The plugin also includes a handy MediaEntry
infolist component, that you can use to display media in your infolists.
This MediaEntry
components works in exactly the same way as the MediaColumn
component. Therefore, I'll assume the thumbnail
and thumbnails
relationships from above.
Next, you can use the MediaColumn
like this:
use RalphJSmit\Filament\MediaLibrary\Infolists\Components\MediaEntry; MediaEntry::make('thumbnail'),
All methods available on the ImageEntry
class are also available on the MediaEntry
class.
MediaEntry::make('thumbnail') ->circular() ->size(40)
If you are getting an error like
App\Models\Post::getMediaLibraryCollectionName()
, please check if the relationship is defined. For example, if you want to use athumbnail
relationship, check if there is a method calledthumbnail()
on your model that returns a relation.
Next, we could use the MediaEntry
to display the thumbnails of the posts from this author:
MediaEntry::make('thumbnails') ->circular() ->stacked()
The media library allows you to add global search to your panel. Normally, Filament only allows to globally search Resources (and not pages), but you can quite easily accomplish a search by creating a custom GlobalSearchProvider
.
Create a class somewhere in your project (an example could be App/Filament/GlobalSearch/GlobalSearchProvider
). Add the following contents:
namespace App\Filament\GlobalSearch; use Filament\GlobalSearch\DefaultGlobalSearchProvider;use Filament\GlobalSearch\GlobalSearchResult;use Filament\GlobalSearch\GlobalSearchResults;use RalphJSmit\Filament\MediaLibrary\FilamentMediaLibrary;use RalphJSmit\Filament\MediaLibrary\Media\Models\MediaLibraryFolder; class GlobalSearchProvider extends DefaultGlobalSearchProvider{ public function getResults(string $query): ?GlobalSearchResults { $builder = parent::getResults($query); $this->addMediaLibraryFolderResults($builder, $query); return $builder; } protected function addMediaLibraryFolderResults(GlobalSearchResults $builder, string $query): void { $mediaLibraryFolders = FilamentMediaLibrary::get()->getModelFolder()::query() ->where('name', 'LIKE', "%{$query}%") ->get(); $globalSearchResults = $mediaLibraryFolders->map(function (MediaLibraryFolder $mediaLibraryFolder): GlobalSearchResult { return new GlobalSearchResult( title: $mediaLibraryFolder->name, url: \RalphJSmit\Filament\MediaLibrary\Media\Pages\MediaLibrary::getUrl(['folder' => $mediaLibraryFolder->getKey()]), ); }); $builder->category(\RalphJSmit\Filament\MediaLibrary\Media\Pages\MediaLibrary::getTitle(), $globalSearchResults); }}
Next, register the custom global search provider in your panel provider(s) where you are using the media library:
$panel ->globalSearch(\App\Filament\GlobalSearch\GlobalSearchProvider::class)
The Media Library has support for the TipTap Editor plugin to upload and/or choose images to insert into your text. The integration will replace the default media upload included in the editor.
To enable the integration, publish the config from the TipTap editor plugin if you didn't publish it yet:
php artisan vendor:publish --tag="filament-tiptap-editor-config"
Next, open the config/filament-tiptap-editor.php
config and replace the media_action
and edit_media_action
key with the following values:
'media_action' => RalphJSmit\Filament\MediaLibrary\FilamentTipTap\Actions\MediaLibraryAction::class, 'edit_media_action' => RalphJSmit\Filament\MediaLibrary\FilamentTipTap\Actions\MediaLibraryEditAction::class,
Now you are able to use the TipTap editor to upload and/or choose images from the media library.
It is also very easy to use the MediaPicker
component outside the admin panel. To enable support for this, you should include the @mediaPickerModal
Blade-directive on every page where you want to use the MediaPicker component.
The @mediaPickerModal
directive should be added before the </body>
-tag. Please make sure to only include the component once to prevent issues.
<!-- In your app.blade.php --><body> <!-- ... --> @mediaPickerModal</body>
Or, on individual pages only:
@once @mediaPickerModal@endonce
The plugin offers an expanding collection of render hooks that allow you to put in any custom HTML that you want. The collection of render hooks is expanded on request (email support@ralphjsmit.com if you want to request a new render hook), in order to be more flexible for future changes I would prefer only having render hooks that are actually used.
Currently, the following render hooks are available:
FilamentMediaLibrary::RENDER_HOOK_MEDIA_INFO_PREVIEW_BEFORE
FilamentMediaLibrary::RENDER_HOOK_MEDIA_INFO_PREVIEW_AFTER
FilamentMediaLibrary::RENDER_HOOK_MEDIA_INFO_TITLE_BEFORE
FilamentMediaLibrary::RENDER_HOOK_MEDIA_INFO_TITLE_AFTER
FilamentMediaLibrary::RENDER_HOOK_MEDIA_INFO_ACTIONS_BEFORE
FilamentMediaLibrary::RENDER_HOOK_MEDIA_INFO_ACTIONS_AFTER
You can register a render hook as follows:
$panel ->renderHook(FilamentMediaLibrary::RENDER_HOOK_MEDIA_INFO_PREVIEW_BEFORE, fn (): View => view('some-view')) ->renderHook(FilamentMediaLibrary::RENDER_HOOK_MEDIA_INFO_PREVIEW_AFTER, fn (): string => Blade::render('<div>Some HTML</div>'))
For example, in a render hook you could want to retrieve the current selected MediaLibraryItem, so that you can access any information via that object. You can use the $this->getMediaLibraryItem()
call to access the current media library item. Next, you can use that model to retrieve any information from your app that you want:
@foreach (Post::whereBelongsTo($this->getMediaLibraryItem(), 'featuredImage')->get() as $post) - {{ $post->title }}@endforeach
The plugin provides several configuration options to override the internal classes it uses. This can be handy in situations where you want to make a small tweak to a certain behaviour or design.
Make sure to always extend the original class.
$plugin // Use the below methods to customize the model used for media library items. // This allows you to override the model for an iten and customize it. // Make sure to always extend the original model, so that you will not accidentally // lose functionality or forget to upgrade functions. ->modelItem(MediaLibraryItem::class) ->modelFolder(MediaLibraryFolder::class)
// The resources and pages to enable in your application.$plugin // From the below array, you can remove the pages you don't need. // If you want to modify a page yourself, you can extend the original page // and register your own class here that extends the page. In that way, you can // customize labels, titles, etc. ->registerPages([ MediaLibrary::class, ]) // The below three classes are the main Livewire-components. If you want to modify // one of the classes, you can create a new class that extends the original class // and update the configuration here accordingly. // NB.: Please note that I cannot guarantee that breaking changes will never happen // inside these classes, so be sure to check if your changes still work after each update. ->uploadMediaComponent(UploadMedia::class) ->mediaInfoComponent(MediaInfo::class) ->browseLibraryComponent(BrowseLibrary::class)
NB.: Please note that I cannot guarantee that breaking changes will never happen inside these classes, so be sure to check if your changes still work after each update.
Do you have the V1 and want to upgrade to V2?
You should have gotten an email with a link to upgrade for a small fee. If you did not get this email or if you want to get it earlier/again, please email me at support@ralphjsmit.com.
RalphJSmit\Filament\MediaLibrary\Media\Components\MediaPicker
to RalphJSmit\Filament\MediaLibrary\Forms\Components\MediaPicker
. The old class is deprecated and will be removed in V3.filament-media-library.models.folder
and value RalphJSmit\Filament\MediaLibrary\Media\Models\MediaLibraryFolder::class
.php artisan vendor:publish --tag="filament-media-library-migrations"php artisan migrate
npm run build
or npm run prod
if you are using a custom theme.The V2 is a paid upgrade to the V1. All license holders have got the ability to purchase the V2/V3 at a discount. If you want to purchase the upgrade from V1 to V2/V3, please go to ralphjsmit.com/filament-plugins, sign in using a magic link, click on the gear icon for your V1 license, click "Upgrade license" and follow the checkout process. You will be able to use your new license immediately.
The Filament Media library plugin has a V3 version that already has support for Filament V3.
If you want to upgrade to Media Library V3 and therefore Filament V3 support, take the following steps:
ralphjsmit/laravel-filament-media-library
'^3.0'
instead of a 2.x version.use RalphJSmit\Filament\MediaLibrary\FilamentMediaLibrary; $panel ->plugin(FilamentMediaLibrary::make())
config/filament-media-library.php
configuration file. Set the values that you want to change using the methods on the FilamentMediaLibrary
class. The methods look very similar to the keys they had in the config. For example, the key disk.visibility
has become a method FilamentMediaLibrary::make()->diskVisibility()
. You can also choose to do nothing. The package will retain compatibility with your current config. Whilst we do recommend to stay up-to-date and migrate your config, it is not a stricty requirement. For example:$panel ->plugin( FilamentMediaLibrary::make() ->diskVisibility('public') ->modelItem(CustomMediaLibraryItemModel::class) ->modelFolder(CustomMediaLibraryFolderModel::class) ->acceptVideo() ->acceptPdf(false) // .. )
400
and 800
conversions (hinting at their square size in px), these conversion names have now changed to small
and medium
. If you prefer to keep the old config file, you do not to change the names/keys. If you changed these config values and you want to migrate them to the new plugin configuration syntax from V3, use the ->conversionSmall(enabled: true, width: 400)
and ->conversionMedium(enabled: true, width: 800)
methods.The V3 is available to all customers who previously purchased a license for V2. If you want to purchase the upgrade from V1 to V3, please send an email to support@ralphjsmit.com
.
If you have a question, bug or feature request, please e-mail me at support@ralphjsmit.com or tag @ralphjsmit on #media-library-pro on the Filament Discord. Love to hear from you!
🙋♂️ Ralph J. Smit