3

Trying to use Laravel Nova with Spatie Media Library. I created upload field like this:

Image::make('Logo')
        ->store(function (Request $request, $model) {
            $model->addMediaFromRequest('logo')->toMediaCollection('manufacturers');
        }),

Seams ok, but Nova still trying to save file name to "logo" column in manufacturers table.

Original excample to customize this field was:

File::make('Attachment')
    ->store(function (Request $request, $model) {
        return [
            'attachment' => $request->attachment->store('/', 's3'),
            'attachment_name' => $request->attachment->getClientOriginalName(),
            'attachment_size' => $request->attachment->getSize(),
        ];
    })
apokryfos
  • 38,771
  • 9
  • 70
  • 114
RomkaLTU
  • 3,683
  • 8
  • 40
  • 63

4 Answers4

3

I found a work around by setting an empty mutator on the model. In your case it would be:

class Manufacturer extends Model implements HasMedia
{
    use HasMediaTrait;

    public function setLogoAttribute() {}

    //...
}

Here's an example of my entire implementation. Note that currently with Nova 1.0.6, the preview() method is not working, it's returning the thumbnail() url.

App/GalleryItem

class GalleryItem extends Model implements HasMedia
{
    use HasMediaTrait;

    public function setImageAttribute() {}

    public function registerMediaConversions(Media $media = null)
    {
        $this->addMediaConversion('thumbnail')
            ->fit(Manipulations::FIT_CROP, 64, 64);

        $this->addMediaConversion('preview')
            ->fit(Manipulations::FIT_CROP, 636, 424);

        $this->addMediaConversion('large')
            ->fit(Manipulations::FIT_CONTAIN, 1920, 1080)
            ->withResponsiveImages();
    }

    public function registerMediaCollections()
    {
        $this->addMediaCollection('images')->singleFile();
    }
}

App/Nova/GalleryItem

class GalleryItem extends Resource
{
    public static $model = 'App\GalleryItem';

    public static $with = ['media'];

    public function fields(Request $request)
    {
        return [
            Image::make('Image')
                ->store(function (Request $request, $model) {
                    $model->addMediaFromRequest('image')->toMediaCollection('images');
                })
                ->preview(function () {
                    return $this->getFirstMediaUrl('images', 'preview');
                })
                ->thumbnail(function () {
                    return $this->getFirstMediaUrl('images', 'thumbnail');
                })
                ->deletable(false);
        ];
    }
}
Staysee
  • 1,887
  • 5
  • 23
  • 30
3

As with Nova 3 (and Laravel 8) you need to return true from the fillUsing or store method:

File::make('Attachment')
    ->store(function (Request $request, $model) {
        $model->addMediaFromRequest('logo')->toMediaCollection('manufacturers');

        return true;
        // This will tell nova that you have taken care of it yourself.
    })

As soon as you return anything but true nova will assume, that it needs to save something to the database. This leads to an error if the field does not exist in db (as to expect with spatie-medialibrary) or it will overwrite your precious data if the field exists but serves another purpose.

Adam Marshall
  • 6,369
  • 1
  • 29
  • 45
gabelbart
  • 73
  • 7
2

Nova allows you to return true from the callback to indicate that the processing is complete and that it shouldn't set any attributes itself.

This is the code that runs the callback:

protected function fillAttribute(NovaRequest $request, $requestAttribute, $model, $attribute)
{
    //...

    $result = call_user_func($this->storageCallback, $request, $model);

    if ($result === true) {
        return;
    }

    if (! is_array($result)) {
        return $model->{$attribute} = $result;
    }

    foreach ($result as $key => $value) {
        $model->{$key} = $value;
    }
}

So either true or any empty array will achieve the same thing, but personally feels clearer to do the former.

1
    Image::make('Logo')
        ->store(function (Request $request, $model) {
            $model->addMediaFromRequest('logo')->toMediaCollection('manufacturers');
        return [];
        }),

Maybe returning an empty array prevent nova from saving the name.

ChrisS
  • 736
  • 2
  • 8
  • 21