Skip to content

Instantly share code, notes, and snippets.

@ns139426
Last active December 1, 2023 08:19
Show Gist options
  • Star 15 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save ns139426/aa4997886cef5b5c9e11de6e0fdffb5a to your computer and use it in GitHub Desktop.
Save ns139426/aa4997886cef5b5c9e11de6e0fdffb5a to your computer and use it in GitHub Desktop.
Duplicate Resource Action for Laravel Nova
<?php
namespace App\Nova\Actions;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Collection;
use Laravel\Nova\Actions\Action;
use Laravel\Nova\Fields\ActionFields;
abstract class DuplicateResource extends Action {
use SerializesModels;
public $showOnDetail = true;
public $showOnIndex = false;
public $showOnTableRow = true;
public $confirmButtonText = 'Duplicate Resource';
public $cancelButtonText = 'Cancel';
public $confirmText = 'Are you sure you want to duplicate this resource?';
public $withoutActionEvents = true;
protected $keepRelations = [];
protected $duplicateRelations = [];
/**
* Perform the action on the given models.
*
* @param ActionFields $fields
* @param Collection $models
*
* @return mixed
*/
public function handle(ActionFields $fields, Collection $models)
{
if ($models->count() !== 1) {
return Action::danger("Cannot duplicate multiple models simultaneously.");
}
$model = $models->first();
$newModel = $model->replicate();
// Override values from fields
foreach ($fields->getAttributes() as $key => $value) {
if(isset($value)){
$newModel->$key = $value;
}
}
$newModel->push();
if (!empty($this->duplicateRelations)) {
// load the relations
$model->load($this->duplicateRelations);
foreach ($model->getRelations() as $relation => $items) {
// works for hasMany
foreach ($items as $item) {
// clean up our models, remove the id and remove the appends
unset($item->id);
$item->setAppends([]);
// create a relation on the new model with the data.
$newModel->{$relation}()->create($item->toArray());
}
}
}
if (!empty($this->keepRelations)) {
// load the fresh model with relations to maintain
unset($model->relations);
$model->load($this->keepRelations);
foreach ($model->getRelations() as $relation => $items) {
// works for hasMany
foreach ($items as $item) {
$newModel->{$relation}()->attach($item);
}
}
}
$newModel->save();
return Action::message($this->getSuccessMessage($model, $newModel, $fields));
}
protected function getSuccessMessage(Model $originalModel, Model $newModel, ActionFields $fields) : String {
return "Resource has been duplicated.";
}
/**
* Get the fields available on the action.
*
* @return array
*/
public function fields()
{
return [];
}
}
@ns139426
Copy link
Author

ns139426 commented Apr 27, 2020

And also when I have: abstract class DuplicateResource extends Action it shows error. So, I removed abstract and it works for one record.

It's written as an abstract class so that you extend it for your own needs rather than just using it directly. If you just want to hack it in place, probably remove $model = $models->first(); and put in a foreach on the $models parameter.

The PHP docs can be pretty tough to read but try https://www.php.net/manual/en/language.oop5.abstract.php. There are probably lots of other good resources on OOP that will help you better understand abstract classes too.

@mikoop79
Copy link

mikoop79 commented Aug 4, 2021

@ns139426 thankyou thankyou thankyou. your work is greatly appreciated. :)

@socertis
Copy link

socertis commented Jun 6, 2022

Thanks a lot. I appreciate you effort.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment