Comments (28)
Alright everyone, we got it (nearly) working. This was really a hard issue to solve and it could still have some issues since I didn't have the time to test it more extensively.
First things first: why is it nearly working? Because we have to wait for a fix on advanced-nova-media-library. I'd suggest you give the existing PR a thumbs up over there to get it moving faster.
How does it work?
- Spatie's
MediaLibrary\HasMedia\HasMedia
interface &MediaLibrary\HasMedia\HasMediaTrait
should both be implemented on the resource model (not on the Flexible layout!) ; - You can now use
Whitecube\NovaFlexibleContent\Concerns\HasMediaLibrary
and implementSpatie\MediaLibrary\HasMedia\HasMedia
interface on your custom layout :
namespace App\Nova\Flexible\Layouts;
use Whitecube\NovaFlexibleContent\Layouts\Layout;
use Whitecube\NovaFlexibleContent\Concerns\HasMediaLibrary;
use Spatie\MediaLibrary\HasMedia\HasMedia;
class MyCustomLayout extends Layout implements HasMedia
{
use HasMediaLibrary;
// ...
}
I sincerely hope the PR on advanced-nova-media-library will be merged soon and that this will fix this issue.
from nova-flexible-content.
Hi all.
We have had the same issue Call to a member function getMedia() on array
which we have resolved in our code.
Hard to provide a full working example as we have custom layout classes and a custom resolver (which saves to Laravel models).
However, below is the relevant function we needed to extend in our layout:
/**
* Resolve the field for display and return the result.
*
* Note, we're extending the method from
* Whitecube\NovaFlexibleContent\Layouts\Layout
*
* We need to override the logic to provide an actual resource (this model)
* to each field for resolveForDisplay().
*
* The parent layout class is
* calling getAttributes() and then passing an array of attributes to each
* field, which doesn't work with Spatie\MediaLibrary (requires a model)
*
* @return array
*/
public function getResolvedForDisplay()
{
$this->fields->each(function ($field) {
$field->resolveForDisplay($this);
});
return $this->getResolvedValue();
}
We traced the issue to a conflict between Laravel\Nova\Fields\Field::resolveForDisplay()
and Whitecube\NovaFlexibleContent\Layouts\Layout::resolveForDisplay()
. The standard nova field expects a $resource
, but the layout is passing through an array of attributes from $this->getAttributes()
, hence the Call to a member function getMedia() on array
.
from nova-flexible-content.
@Nyratas - it would be great if we could get a fix to get it working properly with flexible content. It's a bit of a blocker for us at the minute - we'd be happy to send a bit of money your way to buy yourself some beautiful Belgium beers!
from nova-flexible-content.
Released in v0.1.10, still waiting an update of advanced-nova-media-library.
If you need a quick fix, you could use a fork of advanced-nova-media-library that changes line 105 of src/Fields/Media.php
to:
$attr = $request['__media__'] ?? [];
from nova-flexible-content.
Hi @chrispage1,
Indeed, sorry about that. Am working on a fix as we speak.
from nova-flexible-content.
Fixed in v0.1.11.
from nova-flexible-content.
On my side, everything seems to work exept attributes field is somehow empty.
from nova-flexible-content.
Hi @rbijkercom you need to use the layout key to get the media. I use something like this;
app(MediaRepository::class)->getCollection($model, 'flexible_images_' . $layout_key, []);
from nova-flexible-content.
We'll take a look and see if we can get it working. We'd also accept a PR if anyone wants to give it a go.
from nova-flexible-content.
Hi @reinvanoyen,
I pushed a commit that should solve a similar issue we had with another package. Could you check if the problem still exists when using "whitecube/nova-flexible-content": "dev-master"
?
Thanks!
from nova-flexible-content.
Hi @Nyratas @reinvanoyen - I've just come across this myself and I'm having the same issue, even with the dev-master branch. I'll see if I can dig about...
from nova-flexible-content.
Hi @Nyratas @reinvanoyen - I've just come across this myself and I'm having the same issue, even with the dev-master branch. I'll see if I can dig about...
No joy :( It'd take a long time to truly understand what's going on there for me
from nova-flexible-content.
Hi @reinvanoyen,
I pushed a commit that should solve a similar issue we had with another package. Could you check if the problem still exists when using
"whitecube/nova-flexible-content": "dev-master"
?Thanks!
Hi @Nyratas,
Thanks for looking into this. However, this doesn't solve the issue. I wasn't really expecting it to, tbh. The problem is more that we just don't have a way to use the advanced-nova-media-library fields by using a custom Resolver.
For example, this is my "get" method in my ContentBlockResolver:
class ContentBlockResolver extends Resolver implements ResolverInterface
{
public function get($resource, $attribute, $layouts)
{
$blocks = $resource->blocks()->orderBy('sort_index')->get();
return $blocks->map(function($block) use ($layouts) {
$layout = $layouts->find($block->type);
if( !$layout) {
return;
}
return $layout->duplicateAndHydrate($block->id, [
'id' => $block->id,
'title' => $block->title,
'subtitle' => $block->subtitle,
'text' => $block->text,
'url' => $block->url,
'lat' => $block->lat,
'lng' => $block->lng,
'video_id' => $block->video_id,
]);
})->filter();
}
}
There's just no way the media field will be able to call the "getMedia" method, since it's an array we're returning. This "getMedia" method is how we retrieve our media (https://docs.spatie.be/laravel-medialibrary/v7/basic-usage/retrieving-media/).
from nova-flexible-content.
Hi @reinvanoyen & @chrispage1,
I'm not sure where we're returning an array, because it seems to me we're returning a collection. Inside the map
closure, we're returning layout objects.
This means both returned values are objects, which is good news since you could adapt the one getMedia
should be called on.
I'm not sure which one is used by the media library, but I'm guessing it's not the collection (since its mainly used internally). In case I'm wrong and it is the collection, you could transform your get
resolver in order to return a custom collection, which could contain a getMedia
method (I have no idea what it should do, however).
It would make more sense if the getMedia
method was called on the returned Layout
objects, which is good news because you could assign custom layout classes containing the required method.
Hope this helps, but in case I'm not looking at the right spot, could you specify where the getMedia
method is called on an array? Thanks!
from nova-flexible-content.
So it's triggered on line 198 of Layouts/Layout.php. The reason being is that the $empty flag is set to true. This forces the resolver to pass an empty array but the resolve
method on Advanced Nova Media Library requires its first attribute to be the resource - it won't accept anything else.
So I wonder if in this case the fault is more with Nova Media Libraries resolve method? Either way - how can we work out that the specific series of images belongs to that particular flexible field?
from nova-flexible-content.
We had to pass an array in order to resolve conflicts with a Translatable field (#7) a few months back. Meanwhile we added the Arrayable interface to Layouts, so maybe we don't need to use the $empty
flag anymore and pass the Layout resource to the resolver anyway.
I'll have to give it a look.
from nova-flexible-content.
For the Translatable field (#7) stuff, it's not working with the spatie/nova-translatable package.
The first problem: spatie/nova-translatable is not returning a nova field, instead it's returning a collection of nova fields. Nova flexible content is unable to use this with the current version. We can extend the constructor of Layouts/Layout.php file and loop over the collection and add the fields on their own which will allow us to output the fields. But then we come to problem 2.
The second problem: After the first problem is solved, we see all the additional fields. BUT we can not save them and we also can not see their values. There's some talk about fields with json values inside the issue from above. I haven't been able to resolve this using a custom resolver yet as I don't know the system of flexible content good enough to dig in deeper.
I'm not sure if this is of any help for your problem though (and sorry for hooking into your issue).
I'd be also willing to spend some money on a solution for this (and/or the translation stuff) as I'd need it in a custom package I'm building right now.
Thanks!
from nova-flexible-content.
Hi @tomhatzer, a solution to this issue is in the works as we speak and we're pretty close to have it fully working with advanced-nova-media-library fields.
If you have noticed problems with Spatie's nova-translatable package I would suggest opening a new issue unless you can confirm that the problem is related to this one, which I don't believe it is.
That being said, I have not tried using Spatie's translatable field in Flexible contents before, since we use mrmonat's field, which works fine. If you're in a hurry and can't afford to wait for a potential fix to Spatie's field, I suggest using this alternative which has worked very well for us.
from nova-flexible-content.
Thanks so much for doing this but I'm getting some issues with this unfortunately. I've forked advanced-nova-media-library and made the recommended modification. nova-flexible-content v0.1.10.
I've got a layout called GallerySection
-
<?php
namespace App\Nova\Flexible\Layouts;
use Ebess\AdvancedNovaMediaLibrary\Fields\Images;
use Spatie\MediaLibrary\HasMedia\HasMedia;
use Whitecube\NovaFlexibleContent\Concerns\HasMediaLibrary;
class GallerySection extends Layout implements HasMedia
{
use HasMediaLibrary;
/**
* The layout's unique identifier
*
* @var string
*/
protected $name = 'gallery';
/**
* The displayed title
*
* @var string
*/
protected $title = 'Gallery Section';
/**
* Get the fields displayed by the layout.
*
* @return array
*/
public function fields()
{
return [
Images::make('Gallery Images')
->conversionOnDetailView('small'),
];
}
}
This is for my Post model which has implements Spatie HasMedia & uses HasMediaTrait.
Now in Nova when going to create a post, if I include this layout I get a load failure -
{
"message": "No query results for model [App\\Models\\Post].",
"exception": "Symfony\\Component\\HttpKernel\\Exception\\NotFoundHttpException",
"file": "/var/www/vendor/laravel/framework/src/Illuminate/Foundation/Exceptions/Handler.php",
"line": 204,
"trace": [
{
"file": "/var/www/vendor/laravel/framework/src/Illuminate/Foundation/Exceptions/Handler.php",
"line": 180,
"function": "prepareException",
"class": "Illuminate\\Foundation\\Exceptions\\Handler",
"type": "->"
},
{
"file": "/var/www/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php",
"line": 83,
"function": "render",
"class": "Illuminate\\Foundation\\Exceptions\\Handler",
"type": "->"
},
{
"file": "/var/www/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php",
"line": 32,
"function": "handleException",
"class": "Illuminate\\Routing\\Pipeline",
"type": "->"
},
{
"file": "/var/www/vendor/whitecube/nova-flexible-content/src/Http/Middleware/InterceptFlexibleAttributes.php",
"line": 33,
"function": "Illuminate\\Routing\\{closure}",
"class": "Illuminate\\Routing\\Pipeline",
"type": "->"
},
{
"file": "/var/www/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
"line": 163,
"function": "handle",
"class": "Whitecube\\NovaFlexibleContent\\Http\\Middleware\\InterceptFlexibleAttributes",
"type": "->"
},
{
"file": "/var/www/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php",
"line": 53,
"function": "Illuminate\\Pipeline\\{closure}",
"class": "Illuminate\\Pipeline\\Pipeline",
"type": "->"
}
...
}
from nova-flexible-content.
Any progress on #64
from nova-flexible-content.
I still get the Call to a member function getMedia() on array
error. I am on 0.1.13
of nova-flexible-content and on 2.9.1
of advanced-nova-media-library which are both the most recent I think.
My setup for this is:
use Ebess\AdvancedNovaMediaLibrary\Fields\Images;
use Spatie\MediaLibrary\HasMedia\HasMedia;
use Whitecube\NovaFlexibleContent\Concerns\HasMediaLibrary;
class HtmlLayout extends Layout implements HasMedia {
use HasMediaLibrary;
public function fields() {
return [
Images::make("Image", "my_image")
];
}
}
The fun thing is, that I can see the field and upload files and they are shown as well. But I get the Call to a member function getMedia() on array
in the notification bubble twice (vendor/ebess/advanced-nova-media-library/src/Fields/Media.php:223
).
from nova-flexible-content.
@voidgraphics @Nyratas I have encountered the exact same bug as @bernhardh. For some reason, resolveForDisplay() is being called twice (or so it seems). The first time it gets the proper data and the second time, it fails. I have been trying to track down exactly where it's being called twice, but I haven't had any luck. It is definitely happening within the vendor files.
from nova-flexible-content.
Same behaviour here.
from nova-flexible-content.
Hi @alex-osborn, did you ever get this to work?
from nova-flexible-content.
On my side, everything seems to work exept attributes field is somehow empty.
Same here
from nova-flexible-content.
I ran into exactly this issue. The attributes
field is empty which then causes the cast to return null
, see src/Concerns/HasFlexible.php:134
.
I worked around it by overriding that method and removing that null check in a custom cast.
from nova-flexible-content.
Hi all,
I have been trying to make advanced-nova-media-library fields with nova-flexible-content work for a long time now.
I read this tread, and many others regarding this issue, and tried many suggestions but still no luck.
This is my setup:
"laravel/framework": "8.10",
"laravel/nova": "3.11.1",
"spatie/laravel-medialibrary": "8.10.1",
"ebess/advanced-nova-media-library": "3.3.0",
"whitecube/nova-flexible-content": "0.2.5"
This is how I've added de media to the flexible layout:
namespace App;
use Illuminate\Database\Eloquent\Model;
use Spatie\MediaLibrary\HasMedia;
use Spatie\MediaLibrary\InteractsWithMedia;
use Whitecube\NovaFlexibleContent\Concerns\HasFlexible;
class Page extends Model implements HasMedia
{
use HasFlexible;
use InteractsWithMedia;
protected $guarded = [ 'id' ];
public function registerMediaCollections(): void {
$this->addMediaCollection( 'flexible_images' );
}
namespace App\Nova;
use App\Nova\Flexible\Layouts\ImageText;
use Illuminate\Http\Request;
use Whitecube\NovaFlexibleContent\Flexible;
class Page extends Resource
{
public static $model = \App\Page::class;
public function fields(Request $request)
{
return [
Flexible::make('Body Flexible')
->addLayout( ImageText::class )
];
}
}
namespace App\Nova\Flexible\Layouts;
use Ebess\AdvancedNovaMediaLibrary\Fields\Images;
use Spatie\MediaLibrary\HasMedia;
use Whitecube\NovaFlexibleContent\Concerns\HasMediaLibrary;
use Whitecube\NovaFlexibleContent\Layouts\Layout;
class ImageText extends Layout implements HasMedia
{
use HasMediaLibrary;
protected $name = 'image_text';
protected $title = 'Image Text';
public function fields() {
return [
Images::make('Images', 'flexible_images'),
];
}
}
In the view I loop through the flexible content but it doesn't get the image. I doesn't event run the foreach because it doesn't find a layout.
@foreach($page->flexible('body_flexible') as $layout)
{{ $layout->getMedia('flexible_images') }}
@endforeach
This is what gets stored in the database in the table: pages, column: body_flexible :
[{"layout":"image_text","key":"P0DZKyRuxxncY4t4","attributes":[]}]
The image is also correctly uploaded to the table: media, collection_name: image_text_P0DZKyRuxxncY4t4
The image is also visible the Nova CMS in the flexible content box so somehow Nova knows how to get the image.
Any suggestions on how to display this image in the view?
from nova-flexible-content.
Has anyone managed to get this to work? I'm trying to use the field inside the flexible content but no success =(
from nova-flexible-content.
Related Issues (20)
- Dependent Fields not working HOT 4
- Call to undefined method preventsAccessingMissingAttributes() HOT 3
- "Add layout" dropdown overflow HOT 1
- Not working with replicate function HOT 4
- Dark mode issues HOT 2
- Float-left class not working HOT 1
- Nested flexible layout width HOT 1
- Flexible Content Layouts Truncated When Insufficient Form Content Present HOT 1
- Compatiblity issue with spatie/laravel-medialibrary ^11.4.2
- Resource Details view fails to load in Nova 4.32.13 and up HOT 19
- Laravel 11 Support
- Button cover by card
- The flexible-search-menu does not work. HOT 1
- Regression: Delete button is broken HOT 4
- Can't update models with any flexible field HOT 7
- Flexible isn't opening on Detail and Edit page with Nova v3.3 and Laravel 10
- Flexible not work with DependOn HOT 1
- Spatie Medialibrary incompatibility
- MultiSelect Field
- default Layout
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from nova-flexible-content.