duplicateEntity deletes entries from original entity

I need the ability to remove certain entries when duplicating an entity

Controller

public function duplicate(int $id, int $customMade = 0, int $service = 0): Response
    {
        $this->autoRender = false;

        if (!empty($id) && $id > 0) {
            if ($customMade) {
                $dup = $this->Products->duplicateCustomProduct($id);
            }

            if ($service) {
                $dup = $this->Products->duplicateServiceProduct($id);
            }

            if (!$customMade && !$service) {
                $dup = $this->Products->duplicateEntity($id);
            }

            $dup = $this->Products->save($dup, $this->_getSaveOptions());

            if (!empty($dup) && $dup->id > 0) {
                return $this->redirect(['action' => 'edit', $dup->id]);
            }

            $this->Flash->error(__('The product could not be duplicated. Please check if there is already a product with the model_number "{0}"', $dup->model_number));
        }

        $this->Flash->error(__('Id was not passed'));

        return $this->redirect(['action' => 'index']);
    }

With this function I determine the entries that should be put into the duplicate

public function findAlloysProductsDefault(Query $query, array $options): Query
    {
        return $this->AlloysProducts
            ->find('all', [
                'conditions' => ['default_value' => 1]
            ])
            ->where(['product_id' => $options['id']]);
    }

This function to duplicate is called from the controller

public function duplicateCustomProduct(int $id)
    {
        $DefaultProductAlloy = $this->find('alloysProductsDefault', ['id' => $id]);

        $this->behaviors()
            ->get('Duplicatable')
            ->setConfig('contain', ['ProductImages']);

        $dup = $this->duplicateEntity($id);
        $dup->set(['alloys_products' => $DefaultProductAlloy->toArray()]);

        return $dup;
    }

The duplicate works so far, but in the original entity the entry that matches “‘default_value’ => 1” is deleted and stored in the duplicate.
Why is the original entity also changed here?

UPDATE:
I’m using this Plugin for duplicating Entities GitHub - riesenia/cakephp-duplicatable: CakePHP plugin for duplicating entities including related data
The Method “duplicateEntity” allows me to modify the Entity before saving.

Well, there are quite a few details your code doesn’t show, but…

It all comes down to this line in the controller code:

$dup = $this->Products->save($dup, $this->_getSaveOptions());

Are you certain that $dup is only your new entity and does not have an id set? If the original entity’s id is still set in this ‘duplicate’, you will of course overwrite the original.

There are other possible ways you could inadvertently change the original if your are saving the duplicate as (or with) associated data.

Carefully examine the entity you are preparing to save. Verify it has no id set and that the expected properties are marked dirty and that the expected values are set for those dirty properties.

Hello @dreamingmind, good Point with Entity ID. When i output the dulicated Entity before saving i get this Model without ID. I’m using this Plugin for duplicating Entities GitHub - riesenia/cakephp-duplicatable: CakePHP plugin for duplicating entities including related data
if i modify the duplicated Entity like

 $dup->name = 'New Name'
...

this will only be applied to the duplicated entity.
If i modify the associated Models like “alloys_products” the original and the duplicated Entity will be changed. I got no Idea why this happens.

I expect that there’s an id field not being removed somewhere down the entity tree somewhere, in alloys_products or the join data for it, for example.

That entity appears to be ok (though I think @Zuluru is correct). A real puzzle.

My next move in debugging then would be to test my assumption that

$dup = $this->Products->save($dup, $this->_getSaveOptions());

is the moment when the record is overwritten.

To confirm this I’d debug the entity that shouldn’t be changed at two points. Once as the first action when entering the method. Then I’d rem the save line and just let $dup pass by as though it had been saved, then debug the entity that shouldn’t be changed a second time.

If that ‘source’ entity is what you expect in both cases, then it is proved that the damage is being done by the save. If not then your on a different bug hunt!

If the save is the culprit then you might be looking at a configuration surprise in the Behavior? Is there anyway to simplify the configuration to see if you can isolate a culprit?

Occasionally I’ll temporarily put debugs into Cake Core methods or plugin methods to sort things out. If you get down far enough you can often see the individual entities in a deep nest go by one at a time. For example in some deep save code:

if ($entity instanceof KindThanShouldntChange::class && isset($entity->id) {
   debug(Debugger::trace();
}

This would point to the sequence of events where the process is going off the rails.

@Zuluru you’re so right. Thanks for the Hint!!!
When I inspect the AlloysProducts model after duplicating the product and before saving, there is still a reference to the original product id stored in “product_id”.
As I understand Cake the duplicate gets a new product id after saving but because of the original reference at AlloysProducts here the original entity is changed

@dreamingmind so it looks like i have to find another Way to patch the AlloysProducts Model.
Thanks for your tips with the Strategy how to debug :slight_smile: