F
Filament4mo ago
morty

Spatie Media Library plugin - How to get it to work inside a ManageRelatedRecords page?

I have the Spatie Media Library plugin installed and working in a normal resource, but if I try to use it in a ManageRelatedRecords page, I get SQL errors. Wondering how I can get it to work?
SQLSTATE[23000]: [Microsoft][ODBC Driver 18 for SQL Server][SQL Server]Cannot insert the value NULL into column 'collection_name', table 'prism_test.dbo.media'; column does not allow nulls. INSERT fails. (Connection: sqlsrv, SQL: insert into [media] ([model_id], [model_type], [uuid], [order_column], [updated_at], [created_at]) values (1026, App\Models\Crm\Account, 16cbffaf-e484-46f2-9f56-41d4b00a9910, 1, 2024-08-21 17:48:24.995, 2024-08-21 17:48:24.995))
class ManageAccountMedia extends ManageRelatedRecords
{
protected static string $resource = AccountResource::class;

protected static string $relationship = 'media';

protected static ?string $navigationLabel = 'Media';

public function form(Form $form): Form
{
return $form
->schema([
SpatieMediaLibraryFileUpload::make('test'),
])
->columns(1);
}
}
class ManageAccountMedia extends ManageRelatedRecords
{
protected static string $resource = AccountResource::class;

protected static string $relationship = 'media';

protected static ?string $navigationLabel = 'Media';

public function form(Form $form): Form
{
return $form
->schema([
SpatieMediaLibraryFileUpload::make('test'),
])
->columns(1);
}
}
20 Replies
jigsaw
jigsaw4mo ago
i think you should chain
->collection('collection name')
->collection('collection name')
tp component
morty
mortyOP4mo ago
Tried that, but no go Same SQL is executed doesn't even try to send the collection name
morty
mortyOP4mo ago
morty
mortyOP4mo ago
I'm not sure how to debug this because ray doesn't even get hit here:
No description
morty
mortyOP4mo ago
It appears to be related to the Filament\Tables\Actions\CreateAction class. If I instead use a header action via Filament\Actions\Action rather than a table header action, it all works. Unfortunately I was hoping to make it work with the table header create action to be consistent with button placement. I suppose I can maybe override the ->action() on the CreateAction maybe?
awcodes
awcodes4mo ago
You might need an AttachAction. You can’t just create spatie media items, they require being attached to a record.
toeknee
toeknee4mo ago
It is assigned to model Account, but the collection is not set. so:
SpatieMediaLibraryFileUpload::make('test')->collection('account_media')
SpatieMediaLibraryFileUpload::make('test')->collection('account_media')
morty
mortyOP4mo ago
This doesn't work because it fails at this line: https://github.com/filamentphp/filament/blob/3.x/packages/tables/src/Actions/CreateAction.php#L83 Going to try this now. Attach action isn't working either I gave up and am using the regular Forms\Components\FileUpload component instead which is working great. Would really like to try again with Spatie media library if anyone has any ideas.
toeknee
toeknee4mo ago
I would say to put a recreation repo and we can test
morty
mortyOP4mo ago
Will do, thanks.
morty
mortyOP4mo ago
I created a reproduction repo and github issue here: https://github.com/filamentphp/filament/issues/14031
GitHub
[Filament Spatie Media Library Plugin] Does not work inside a Manag...
Package filament/spatie-laravel-media-library-plugin Package Version v3.2.107 Laravel Version v11.21.0 Livewire Version v3.5.6 PHP Version PHP 8.2 Problem description The spatie media library plugi...
toeknee
toeknee4mo ago
Ok I see why now, you are building it via a media relationship, whereas the SpatieMedia field is designed against a model, not a relationship.... So it try's to save as if it's a relationship and misses all the required elements off. what you actually want is an action, let me see if I can do this This will work as a table headAction for allowing 1 file
Tables\Actions\Action::make('add_media')
->form([
SpatieMediaLibraryFileUpload::make('file')
->collection('testing')
->model($this->getOwnerRecord())
->hiddenLabel()
->required(),
])
->action(function ($record, array $data) {

}),
Tables\Actions\Action::make('add_media')
->form([
SpatieMediaLibraryFileUpload::make('file')
->collection('testing')
->model($this->getOwnerRecord())
->hiddenLabel()
->required(),
])
->action(function ($record, array $data) {

}),
However, the way spatie media works is the collection defines what can be uploaded. So if you have 1 file it'll remove the others...
morty
mortyOP3mo ago
I tested your solution and it does work, but I don't understand why it only allows one file? Can you clarify that for me?
toeknee
toeknee3mo ago
As I understand it, once you add a file to the collection the old entries for that model are cleared. It expects them to be loaded into the array to avoid ones being left over
morty
mortyOP3mo ago
Hmm, I might have to go the custom livewire component route then Thanks for the help
toeknee
toeknee3mo ago
You could allow multiple in the field which and fill the form with the record But adding wouldn't be quite the same
morty
mortyOP3mo ago
Multiple did allow me to upload multiple but didn't fill the form automatically. Though, I'm sure I could get that working. It does seem weird that it's essentially "syncing" rather than adding, but like you said it's setup to work that way instead of on a relationship. I think this is the part of the plugin code that is doing it. I know this isn't the default functionallity of spatie media library though because in another app that isn't using Filament, but just straight Livewire, I've implemented this and it works to add instead of sync/delete.
$this->saveRelationshipsUsing(static function (SpatieMediaLibraryFileUpload $component) {
$component->deleteAbandonedFiles();
$component->saveUploadedFiles();
});
$this->saveRelationshipsUsing(static function (SpatieMediaLibraryFileUpload $component) {
$component->deleteAbandonedFiles();
$component->saveUploadedFiles();
});
public function deleteAbandonedFiles(): void
{
/** @var Model&HasMedia $record */
$record = $this->getRecord();

$record
->getMedia($this->getCollection() ?? 'default')
->whereNotIn('uuid', array_keys($this->getState() ?? []))
->when($this->hasMediaFilter(), fn (Collection $media): Collection => $this->filterMedia($media))
->each(fn (Media $media) => $media->delete());
}
public function deleteAbandonedFiles(): void
{
/** @var Model&HasMedia $record */
$record = $this->getRecord();

$record
->getMedia($this->getCollection() ?? 'default')
->whereNotIn('uuid', array_keys($this->getState() ?? []))
->when($this->hasMediaFilter(), fn (Collection $media): Collection => $this->filterMedia($media))
->each(fn (Media $media) => $media->delete());
}
awcodes
awcodes3mo ago
you could extend the field with your own and override whatever functionality you need to.
morty
mortyOP3mo ago
Thanks, I'll probably do that but will be another day
Adam Holmes
Adam Holmes2mo ago
Hi @morty, did you make any progress on this? I think I'm in a similar boat where I would like to have the media library as a ManageRelatedRecord page. Essentially, I'd like to upload files (from a create page) and then display them in a table like I usually would on ManageRelatedRecords page. The route that I'm heading down is a bit messy where I end up with 2 morphMany relationships which I'd rather avoid.
Want results from more Discord servers?
Add your server