advanced-nova-media-library icon indicating copy to clipboard operation
advanced-nova-media-library copied to clipboard

Use within BelongsToMany pivot field

Open SunnyDayGuide opened this issue 4 years ago • 4 comments

I have a Many to Many relationship between Markets & Categories using a custom pivot model. I have the Spatie media conversions/collections, etc defined there.

class MarketCategory extends Pivot implements HasMedia
{
    use HasMediaTrait;

    public function registerMediaCollections()
    {
        $this->addMediaCollection('slider')
            ->registerMediaConversions(function (Media $media) {
                $this->addMediaConversion('full')->withResponsiveImages();
            });
    }
}

This is working as expected attaching the Media objects to the pivot model in a non-Nova environment.

When I try to attach Media to the pivot model in Nova using a BelongsToMany pivot field, I get the following exception: Call to undefined method Illuminate\Database\Eloquent\Relations\Pivot::getMedia()

Here is my pivot field:

BelongsToMany::make('Categories')
    ->fields(function () {
        return [
            Text::make('Title')->rules('required', 'max:255'),

            Trix::make('Body'),

            Images::make('Slider Images', 'slider')
                ->conversion('full')
                ->multiple()
                ->fullSize()    
                ->hideFromIndex(),
        ];
    }),

Any ideas what I am doing wrong? Is the Images field not meant to work within a BelongsToMany? Any sort of direction would be much appreciated.

Laravel v5.8.30 Nova v2.0.6

SunnyDayGuide avatar Aug 06 '19 17:08 SunnyDayGuide

Same here. @SunnyDayGuide did you solve this by chance?

pleone avatar Apr 28 '20 14:04 pleone

I'll write down how I solved it if anyone in the future might need it: my solution was to pass the 'id' field to the pivot fields. I inspected the resource variable passed to the resolve function and somehow the resource had the id field missing so i guess the media library was not able to find the related objects.

In my model: return $this->belongsToMany(Acme::class, 'pivot_table_class_name')->using(CustomModelPivot::class)->withPivot('id', ... );

The id is what you need to pass to make it work.

Cheers

pleone avatar Apr 28 '20 17:04 pleone

I'm getting the same issue (Nova 3.9.2, Laravel 7.28.1). I've tired the above suggestion but still hit issues.

I've done a bit of debugging, I think it's down to a validation call from Nova: Laravel\Nova\Http\Controllers\AttachedResourceUpdateController -> validate which eventually calls: Ebess\AdvancedNovaMediaLibrary\Fields\Media -> resolve

The problem is resolve is passed a standard Pivot model, instead of the custom intermediate model table.

This is down to the AttachedResourceUpdateController calling $model->setRelation AFTER validation completes.

You can fix this issue by wrapping resolve in a try catch block:

/**
     * @param HasMedia|HasMediaTrait $resource
     * @param null $attribute
     */
    public function resolve($resource, $attribute = null)
    {
        $collectionName = $attribute ?? $this->attribute;

        if ($collectionName === 'ComputedField') {
            $collectionName = call_user_func($this->computedCallback, $resource);
        }

        try {
            $this->value = $resource->getMedia($collectionName)
                ->map(function (\Spatie\MediaLibrary\MediaCollections\Models\Media $media) {
                    return array_merge($this->serializeMedia($media), ['__media_urls__' => $this->getConversionUrls($media)]);
                });

            if ($collectionName) {
                $this->checkCollectionIsMultiple($resource, $collectionName);
            }
        } catch (\Exception $ex) {
        }
    }

This seems to allow the validation call to complete, then the subsequent save call to this method works perfectly.

I don't think this is the best solution, but I hope this helps you find a solution.

ArronKing avatar Sep 10 '20 13:09 ArronKing

Same problem here with MorphPivot:

Call to undefined method Illuminate\Database\Eloquent\Relations\Pivot::getMedia()

joserick avatar Feb 09 '22 06:02 joserick