Laravel Nova field for managing the Spatie media library.
With this package you can:
- create, update, delete and sort your media files
- update media attributes (filename, custom properties, etc)
- display media on the index view
- crop images
- Screenshots
- Requirements
- Installation
- Usage
- What about forms?
- Display media on the index view
- Custom media realation
- Crop
- Labels
- Thumbnail
- Thumbnail size
- Thumbnail title
- Thumbnail description
- Single media collection
- Store and Replace callbacks
- Custom download url
- Validation
- Sorting
- Custom media resource
- Authorization Gates 'view', 'update' and 'delete'
- Changelog
- Alternatives
- License
- Laravel Nova >= 1.2.0
This package can be installed via command:
composer require dmitrybubyakin/nova-medialibrary-field
In your NovaServiceProvider
register default media resource (only if you don't want to use your own one):
public function boot()
{
parent::boot();
Nova::resources([
\DmitryBubyakin\NovaMedialibraryField\Resources\Media::class,
]);
}
class Post extends Resource
{
// ...
public function fields(Request $request)
{
return [
// ...
Medialibrary::make('Images'), // it uses default collection
Medialibrary::make('Images', 'post_images'), // you can use collection which you want
Medialibrary::make('Images', 'post_images', MyMediaResource::class), // you can use own Media resource
];
}
}
Medialibrary field is shown only on index and details views. If there is any reason to show it on forms, let me know.
Medialibrary::make('Images')
->mediaOnIndex(), // display first media
Medialibrary::make('Images')
->mediaOnIndex(3), // display first 3 media
Medialibrary::make('Images')
->mediaOnIndex(function (Collection $mediaItems) {
return $mediaItems->where('extension', 'jpg'); // filter media
})
class Post extends Model implements HasMedia
{
public function featuredMedia(): MorphMany
{
return $this->media()->where('collection_name', 'featured');
}
}
Medialibrary::make('Featured Image', 'featured')
->relation('featuredMedia'),
Medialibrary::make('Featured Image', 'featured')->croppable(),
Medialibrary::make('Awesome Media', 'awesome_collection')
->label($title, $condition, $trueColor = 'var(--success)', $falseColor = 'var(--danger)'),
->label('Active', 'custom_properties->active'),
->label('Active', 'custom_properties->active', 'var(--success)', null), // visible only when the condition is true
->label('Active', 'custom_properties->active', null, 'var(--danger)'), // visible only when the condition is false
->label('Size > 1MB', function (Media $media) {
return $media->size >= 1024 * 1024;
}),
Medialibrary::make('Featured Image', 'featured')
->thumbnail('thumbnailConversion'),
Medialibrary::make('Featured Image', 'featured')
->thumbnail(function (Media $media) {
return 'https://dummyimage.com/300x300/ffffff/000000&text=' . strtoupper($media->extension);
}),
// The default width of a thumbnail is 8 rem.
// The bigThumbnails method makes a singular thumbnail twice as wide as the default.
Medialibrary::make('Featured Image', 'featured')
->thumbnail('thumbnailConversion')
->bigThumbnails(),
By default, thumbnails are available only for the files with one of the following mime types: [image/jpeg, image/gif', image/png]
.
This is how you can override the default setting:
Medialibrary::make('Featured Image', 'featured')
->imageMimes('image', 'mimes', 'that', 'you', 'need')
->thumbnail(...)
Medialibrary::make('Featured Image', 'featured')
->thumbnailSize('14rem', '9rem') // width, height
->thumbnailSize('10rem') // width = height
Medialibrary::make('Featured Image', 'featured')
->thumbnailTitle('custom_properties->title') // $media->file_name is used by default
Medialibrary::make('Featured Image', 'featured')
->thumbnailTitle(function (Media $media) {
return $media->name;
})
You can add a short description below the thumbnail title.
Medialibrary::make('Featured Image', 'featured')
->thumbnailDescription('custom_properties->description', $limit = 75) // hidden by default
Medialibrary::make('Featured Image', 'featured')
->thumbnailDescription(function (Media $media) {
return 'Size: ' . $media->humanReadableSize;
})
class Post extends Model implements HasMedia
{
public function registerMediaCollections()
{
$this->addMediaCollection('featured')
->singleFile(); // just define it here
}
}
Medialibrary::make('Featured Image', 'featured'), // nothing to do here
If you want to do someting before media is saved, you can use storeUsing
method.
Medialibrary::make('Images', 'post_images')
->storeUsing(function (FileAdder $fileAdder, UploadedFile $file) {
return $fileAdder->withCustomProperties(['description' => $this->resource->title]);
})
When you are using a single media collection, you can also use replaceUsing
method which allows you to access the old media.
Medialibrary::make('Featured Image', 'featured')
->replaceUsing(function (FileAdder $fileAdder, Media $oldFile, UploadedFile $file) {
return $fileAdder
->usingFileName($oldFile->file_name)
->withCustomProperties($oldFile->custom_properties);
})
You can change URL of the download button.
Medialibrary::make('Featured Image', 'featured')
->downloadUsing(function (Media $media) {
return <...>;
})
Validation works only when you are storing a new file.
Medialibrary::make('Featured Image', 'featured')
->rules('max:1024', 'image')
->accept('image/*') // this is an attribute for input. <input type="file" accept="image/*">
Medialibrary::make('Images', 'post_images')
->sortable()
class MyMedia extends Resource
{
public static $model = 'Spatie\MediaLibrary\Models\Media';
public static $displayInNavigation = false;
public function fields(Request $request): array
{
return [
ID::make(),
Text::make('Filename', 'file_name'),
Textarea::make('Description', 'custom_properties->description')->alwaysShow(),
Text::make('Size')->displayUsing(function () {
return $this->resource->humanReadableSize;
})->exceptOnForms(),
];
}
}
class Post extends Resource
{
public function fields(Request $request)
{
return [
Medialibrary::make('Images', 'collection', MyMedia::class),
];
}
}
To view, update and delete uploaded media, you need to setup some gates. You can use the store and replace callbacks to store additional information to the custom_properties. The additional information can be used inside the gates for authorization.
Gate::define('view', function ($user, $media) {
return true; // view granted
});
Gate::define('update', function ($user, $media) {
return true; // update granted
});
Gate::define('delete', function ($user, $media) {
return true; // deletion granted
});
You can also use the policy.
class MediaPolicy
{
use HandlesAuthorization;
public function view(User $user, Media $media): bool
{
return true;
}
public function update(User $user, Media $media): bool
{
return true;
}
public function delete(User $user, Media $media): bool
{
return true;
}
}
class AuthServiceProvider extends ServiceProvider
{
protected $policies = [
Media::class => MediaPolicy::class,
];
//...
}
Please see the CHANGELOG for more information about the most recent changed.
- https://github.com/jameslkingsley/nova-media-library
- https://github.com/ebess/advanced-nova-media-library
The MIT License (MIT). Please see License File for more information.