F
Filament3mo ago
Joshua

Form Saving with BelongsToMany Giving Headache

Will preface this saying I'm definitely somewhat new to filament, but using a preexisting project someone made to try and learn by expanding on it through the filament docs. Running into a bit of a puzzle that I'm hoping someone has a "duh" answer for. I have a Product Model (and ProductResource accordingly), as well as a Wallet model. A product can be associated with MANY wallets (BelongsToMany), because a wallet can also be attached to many products. The basic explanation for this is that when selling a product you can determine (infinite) splits for the sale to be spread out across wallets with configurable %'s. My Product Model has a:
public function wallets(): BelongsToMany
{
return $this->belongsToMany(Wallet::class, 'product_wallet')
->withPivot('percentage')
->withTimestamps();
}
public function wallets(): BelongsToMany
{
return $this->belongsToMany(Wallet::class, 'product_wallet')
->withPivot('percentage')
->withTimestamps();
}
My Wallet model has the same, vice versa. Here is the form component that handles it: https://gist.github.com/Joshinn-io/c6a680b6b52760605cc4ec812685522a This ends up with a pivot table that looks like the attached image. I was able to get saving working by overriding handleRecordUpdate on the EditProduct.php part of ProductResource, as shown in the image with some data in the table and from this code:
protected function handleRecordUpdate(\Illuminate\Database\Eloquent\Model $record, array $data): \Illuminate\Database\Eloquent\Model
{
$walletsData = $data['wallets'] ?? [];
unset($data['wallets']);

$record->update($data);

foreach ($walletsData as $walletData) {
$record->wallets()->attach($walletData['wallet_id'], ['percentage' => $walletData['percentage']]);
}

return $record;
}
protected function handleRecordUpdate(\Illuminate\Database\Eloquent\Model $record, array $data): \Illuminate\Database\Eloquent\Model
{
$walletsData = $data['wallets'] ?? [];
unset($data['wallets']);

$record->update($data);

foreach ($walletsData as $walletData) {
$record->wallets()->attach($walletData['wallet_id'], ['percentage' => $walletData['percentage']]);
}

return $record;
}
That feels a little bit too manualy, but it works so it was a step in the right direction. The part I'm trying to resolve now, is how to populate that date back into the repeater when you load that page so you can see the wallets already configured for that product, because right now it obviously loads empty. I did find this section on the wiki that has you go about it a totally different way ( https://filamentphp.com/docs/3.x/forms/fields/repeater#integrating-with-a-belongstomany-eloquent-relationship ) and tried to set that up with a ProductWallet.php pivot but that seemed to simply not like any ->relationship() setup I fed it all. Any help is appreciated, thanks a ton!
Gist
Snippet of ProductResource.php
Snippet of ProductResource.php. GitHub Gist: instantly share code, notes, and snippets.
No description
1 Reply
Joshua
Joshua3mo ago
Here is a picture of how the form looks on the frontend, for more context.
No description