Cloning relationships with ->replicate()

I'm using v2 and added the ->replicate method. Works great. Making some changes in the beforeReplicaSaved hook and all is well. I need to save the relationships. Is this just a matter of doing it the laravel way (per the docs) and just doing that in the after() method or is there another way in Filament? Just wanted to check before I do this the hard way or something lol.
5 Replies
Chrispian
Chrispian10mo ago
I found the answer, Dan has already covered this. Has to be done manually. His reply for reference: https://discord.com/channels/883083792112300104/883085291722788964/1011540053123661884
Chrispian
Chrispian10mo ago
In case anyone tries this, in the afterReplicaSaved method, inject the $record (original) and $replica (copy). Then you can do the following. My model is called Tile
foreach ( $record->roles as $role ) {
$replica->company_roles()->attach( $role->id );
}
foreach ( $record->roles as $role ) {
$replica->company_roles()->attach( $role->id );
}
cheesegrits
cheesegrits10mo ago
If you have a lot of relations (like I do) and have a lot of models you want to have duplication actions on (to where it would be a major pain to manually do all the record copying) you can also roll your own action, and use bkwld/cloner, which adds a duplicate() method to your model, which you can customize with the relations you do or don't want cloned. Then in a custom action, just do ...
Action::make('duplicate')
->action(function (YourModel $record): void {
$record->duplicate();
})
->icon('heroicon-s-document-duplicate'),
Action::make('duplicate')
->action(function (YourModel $record): void {
$record->duplicate();
})
->icon('heroicon-s-document-duplicate'),
YourModel might look like ...
use Bkwld\Cloner\Cloneable;

class YourModel extends Model
{
use Cloneable;

protected $cloneable_relations = [
'foo',
'bar',
'garply',
];

// etc
}
use Bkwld\Cloner\Cloneable;

class YourModel extends Model
{
use Cloneable;

protected $cloneable_relations = [
'foo',
'bar',
'garply',
];

// etc
}
https://github.com/BKWLD/cloner
GitHub
GitHub - BKWLD/cloner: A trait for Laravel Eloquent models that let...
A trait for Laravel Eloquent models that lets you clone a model and it's relationships, including files. Even to another database. - GitHub - BKWLD/cloner: A trait for Laravel Eloquent mode...
cheesegrits
cheesegrits10mo ago
The other useful thing I find with rolling my own duplicate action is when I need to override one or two fields on the duplicate. For example, here's where I let the user duplicate a DailyLog (for aircraft flights), but we know the flight_date needs to be changed ...
Action::make('duplicate')
->mountUsing(fn (Forms\ComponentContainer $form, DailyLog $record) => $form->fill([
'flight_date' => $record->flight_date,
]))
->action(function (DailyLog $record, array $data): void {
$record->fill($data);
$record->duplicate();
})
->form([
DatePicker::make('flight_date'),
])
->icon('heroicon-s-document-duplicate'),
Action::make('duplicate')
->mountUsing(fn (Forms\ComponentContainer $form, DailyLog $record) => $form->fill([
'flight_date' => $record->flight_date,
]))
->action(function (DailyLog $record, array $data): void {
$record->fill($data);
$record->duplicate();
})
->form([
DatePicker::make('flight_date'),
])
->icon('heroicon-s-document-duplicate'),
... which pops up a form with just "Flight Date", which then overrides the flight_date for the data that gets copied to the new record.
Chrispian
Chrispian10mo ago
Very nice! I love what you cooked up here. I'm definitely adding this to my snippets collection and will use this pattern in the future. I like how clean this is! Well done.