nova-flexible-content icon indicating copy to clipboard operation
nova-flexible-content copied to clipboard

"Origin HasMedia model not found"

Open apepindev opened this issue 5 years ago • 5 comments

I followed the guide on adding media using the advanced-nova-media-library package and I'm having an issue. The resource with the custom layout is working fine saving and retrieving images. The issue is trying to get the images back from it to render on my page. Every time I call getMedia() on the layout instance in my viewI get an exception saying "Origin HasMedia model not found". What I did was;

  • Implemented Spatie\MediaLibrary\HasMedia\HasMedia interface and Whitecube\NovaFlexibleContent\Concerns\HasFlexible trait to my Article model.
  • Implemented Spatie\MediaLibrary\HasMedia\HasMedia interface and Whitecube\NovaFlexibleContent\Concerns\HasMediaLibrary trait to my custom SingleImage Flexible Layout class.

My Article model also has this...

public function getFlexibleContentAttribute()
{
    return $this->flexible('content', [
        'image' => SingleImage::class
    ]);
}

So the getMedia() method is in the layout class but for some reason Flexible::getOriginModel() in the trait just returns null, therefore giving the exception. I fear I'm missing something trivial here.

I should also mention I'm using 0.2.0 as later versions require a newer version of advanced-nova-media-library and that then requires spatie/laravel-medialibrary v8 that requires php 7.4+ where I'm currently on 7.2. Upgrading php isn't ideal right now but if it's the only option then I'll probably have to.

apepindev avatar Jun 14 '20 21:06 apepindev

I hit the same issue today. My setup is like below:

class Content extends Resource;
{
	public function fields(Request $request)
	{
		return [
			Flexible::make('Content')
				->addLayout(IconListLayout::class)
		];
	}
}


class IconListLayout extends Layout
{
	public function fields()
	{
		return [
			Flexible::make('Icons')
				->addLayout(IconLayout::class)
		];
	}
}


class IconLayout extends Layout implements HasMedia
{
	use HasMediaLibrary;

	public function fields()
	{
		return [
			Images::make('Image', 'icon_image'),
		];
	}
}

As a horrible hack around the issue, I'm setting the static::$model property of the Flexible class to the database model. My view below:

@php
// Cast the nested flexible
$icons = $content->flexible('icons', [
	'icon' => \OpPortal\Nova\ContentLayouts\IconLayout::class,
]);

// Manually set the Flexible model to the original Database model
\Whitecube\NovaFlexibleContent\Flexible::$model = $contents;
@endphp

<ul class="icon_list">
	@foreach($icons as $icon)
		<li class="icon_list-icon">
			<img src="{{ $icon->getFirstMediaUrl('icon_image') }}" alt="">
			<h4 class="icon_list-icon-title">
				{{ $icon->title  }}
			</h4>
			<p class="icon_list-icon-desc">
				{{ $icon->description  }}
			</p>
		</li>
	@endforeach
</ul>

I'd like to find a nicer solution to this as my workaround is far from ideal.

adamcmoore avatar Jun 15 '20 12:06 adamcmoore

Thank you! Adding that late static bind to my model worked for me.

    public function getFlexibleContentAttribute()
    {
        Flexible::$model = $this;

        return $this->flexible('content', [
            'image' => SingleImage::class
        ]);
    }

I agree though that this should be implicitly set.

apepindev avatar Jun 15 '20 18:06 apepindev

Can you elaborate on this - I tried your method above but it still failed.

Slgoetz avatar Sep 26 '20 18:09 Slgoetz

I'm having this issue too, it causes a huge problem on nested flexible layouts.

jakecausier avatar Sep 28 '20 14:09 jakecausier

This might be irrelevant now, but I was having trouble generating URLs for images for nested layouts. Landed on this thread and it helped figure this out. Maybe this helps someone else.

Using Flexible::$model = $this makes it work in the frontend, but causes Nova to crash. I set it up like this instead and it works out great.

public function getPictureAttribute()
{
    while(is_subclass_of($this->model, Layout::class)) {
        $this->setModel($this->model->model);
    }
    return $this->getFirstMediaUrl('picture');
}

salmanhijazi avatar Aug 29 '22 23:08 salmanhijazi