Reputation: 733
In my CakePHP 3 app, I have a somewhat elaborate tree of entities that I need to clone and save.
The root of the structure is a Questionnaire, a Questionnaire hasMany Questions, each Question hasMany Fields, etc. (it goes deeper). Now I want the user to be able to define a new questionnaire by copying an old one. Then they can change whatever they need.
I can get a dump of what I need to copy by using $questionnaire->$this->Questionnaires->get($id)
with the appropriate contain fields. Is there a clever way to save this as a bunch of new entities while preserving the data and the structure between them?
Upvotes: 5
Views: 6021
Reputation: 457
I think the best possible way would be following work flow:
$this->Questionnaires->newEntity($arrayData, ['associated' => ['Questions', '...']]);
AFAIK there's no "smarter" way of cloning an entity with associations in Cake 3 :-)
Upvotes: 6
Reputation: 11
$original = $this->Table->get($id)->toArray();
$copy = $this->Table->newEntity();
$copy = $this->Table->patchEntity($copy, $original);
unset($copy['id']);
// Unset or modify all others what you need
$this->Table->save($copy);
Work perfectly like this :)
Upvotes: 1
Reputation: 11
use EntityInteface toArray() to get all its fields:
$newEtity = $someTable->newEntity($oldEtity->toArray());
unset($newDevice->created);
unset($newDevice->id);
$someTable->save($newEntity);
Upvotes: 1
Reputation: 5256
Here's the way I did it when I needed something similar (adapted to the Questionnaire example):
// load the models
$this->loadModel('Questionnaire');
$this->loadModel('Questions');
// get the questions to questionnaire association - will need the PK name
$qAssoc = $this->{'Questions'}->associations()->get('Questionnaire');
// get the existing entity to copy
$existingEntity = $this->{'Questionnaire'}->get($id, [
'contain' => ['Questions'],
]);
// clean up the existing entity
$existingEntity->unsetProperty($this->{'Questionnaire'}->getPrimaryKey());
$existingEntity->unsetProperty('created');
$existingEntity->unsetProperty('modified');
// clean up the associated records of the existing entity
foreach ($existingEntity->questions as &$q) {
$q->unsetProperty($this->{'Questions'}->getPrimaryKey());
$q->unsetProperty($qAssoc->getForeignKey());
}
// create a new entity and patch it with source data
$newEntity = $this->{'Questionnaire'}->patchEntity(
$this->{'Questionnaire'}->newEntity(),
$existingEntity->toArray()
);
// save the new entity
$result = $this->{'Questionnaire'}->save($existingEntity);
References:
Upvotes: 0
Reputation: 443
You could also use this plugin. You only have to configure the behavior and it gives you other functionalities, like setting default values or appending text to some field.
Upvotes: 6