I am trying to implement a "Clone" action on a page listing entities ("Circuits"). The workflow is the following:
- user selects an entity then selects the "Clone" action in a dropdown
- the CircuitsController::indexAction method is fired, redirects the user to the CircuitsController::editAction page and pass along the Circuit's ID and a GET parameter $is_clone = true;
- user modifies whatever he wants, then submits
- the CircuitsController::editAction method sees that a clone request has been made, clones the Circuit entity, persist it then flush the EntityManager.
My issue here is that when the EntityManager::flush method is called, two strictly identical INSERT queries are performed, thus leading to a rollback and no new circuit persisted.
Here is the portion of code from the CircuitsController::indexAction that redirects:
case 'duplicate':
    $this->denyAccessUnlessGranted('ROLE_NETWORK', null, 'Insufficient rights to perform selected action.');
    if (count($formData['circuits']) != 1) {
        throw new \RuntimeException('Cannot duplicate more than one item.');
    }
    /* 'circuits' key points to an array of circuits */
    $circuit = $formData['circuits'][0];
    return $this->redirect($this->generateUrl('net_dev_web_circuits_edit',
                                              ['id' => $circuit->getId(),
                                               'type' => $type,
                                               'clone' => true]));
My CircuitsController::editAction:
public function editAction(Request $request, Circuit $circuit, $type = 'mnms') {
    $this->denyAccessUnlessGranted('ROLE_NETWORK', null, 'Insufficient rights to perform selected action.');
    $em = $this->getDoctrine()->getManager();
    $clone = $request->query->get('clone');
    $circuitForm = $this->buildCircuitsForm($circuit, $type, ['is_clone' => $clone]);
    if (empty($clone)) {
        $lcmForm = $this->generateLcmForm($em, $circuit);
    }
    else {
        $lcmForm = null;
    }
    if ($request->isMethod('POST')) {
        if ($circuitForm->handleRequest($request)->isValid()) {
            if ($clone) {
                $em->detach($circuit);
                $circuit = clone $circuit;
                $em->persist($circuit);
                $endPointRepo = $em->getRepository('NetDevCoreBundle:EndPoint');
                $mnms = $circuit->getMnmsCircuit();
                $endPoints = $endPointRepo->findByCircuit($mnms);
                foreach ($endPoints as $endPoint) {
                    $device = $endPoint->getDevice(); /* @var $device Device */
                    $defaultEndPoint = (new EndPoint())
                                     ->setCircuit($circuit)
                                     ->setDevice($device)
                                     ->setSite($endPoint->getSite())
                                     ;
                    $device->addCircuit($circuit);
                    $em->persist($defaultEndPoint);
                }
            }
            $em->flush();
            $request->getSession()->getFlashBag()->add('notice', 'Circuit saved');
            return $this->redirect($this->generateUrl('net_dev_web_circuits_edit', array('type' => $type,
                                                                                         'id' => $circuit->getId())));
        }
        /* [.. unrelated code (I hope) to get the edit form ..] */
    }
Following is the __clone method of my entity:
public function __clone() {
    if ($this->id) {
        $this->id = null;
        $this->listenPops = new ArrayCollection();
        $this->endPoints = new ArrayCollection();
    }
}
And finally, the two issued SQL statements:
#20 0.29 ms:
"START TRANSACTION"
Parameters: [null] 
#21 0.29 ms:
INSERT INTO Circuit (
  two_way, circuit_name, circuit_type, 
  mtu, port_bindings, user_enable, 
  bandwidth, tierLevel, translate, 
  crossconnect, header_compression, 
  padding_removal, untag_enable, landside_tx_duplicate_enable, 
  landside_tx_duplicate_vlan_id, 
  priority, trunk_force_mask, connection_number, 
  aptUserVlanIds, user_max_age, validationDate, 
  synchronizationDate, updatedAt, 
  macAddresses, vlan_id, mnms_circuit, 
  parent_route, customer
) 
VALUES 
  (
    ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 
    ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?
  )
Parameters: { 1: 1, 2: MNMS_Tier1_ZZZ_XX_3171, 3: mnms, 4: 23, 5: 1, 6: 1, 7: 100, 8: 0, 9: 0, 10: '', 11: 0, 12: 0, 13: 0, 14: 0, 15: 0, 16: 1, 17: 0, 18: 1, 19: 'a:4:{i:1;N;i:2;N;i:3;N;i:4;N;}', 20: null, 21: '2015-08-19 11:33:42', 22: null, 23: '2015-09-07 18:48:37', 24: 'a:0:{}', 25: 233, 26: null, 27: 13, 28: 64 } 
#22 0.00 ms:
INSERT INTO Circuit (
  two_way, circuit_name, circuit_type, 
  mtu, port_bindings, user_enable, 
  bandwidth, tierLevel, translate, 
  crossconnect, header_compression, 
  padding_removal, untag_enable, landside_tx_duplicate_enable, 
  landside_tx_duplicate_vlan_id, 
  priority, trunk_force_mask, connection_number, 
  aptUserVlanIds, user_max_age, validationDate, 
  synchronizationDate, updatedAt, 
  macAddresses, vlan_id, mnms_circuit, 
  parent_route, customer
) 
VALUES 
  (
    ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 
    ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?
  )
Parameters: { 1: 1, 2: MNMS_Tier1_ZZZ_XX_3171, 3: mnms, 4: 23, 5: 1, 6: 1, 7: 100, 8: 0, 9: 0, 10: '', 11: 0, 12: 0, 13: 0, 14: 0, 15: 0, 16: 1, 17: 0, 18: 1, 19: 'a:4:{i:1;N;i:2;N;i:3;N;i:4;N;}', 20: null, 21: '2015-08-19 11:33:42', 22: null, 23: '2015-09-07 18:48:37', 24: 'a:0:{}', 25: 233, 26: null, 27: 13, 28: 64 } 
#23 3.96 ms 
"ROLLBACK"
Parameters: [null] 
I have been fiddling around with that but to no avail. I am wondering if this would not be caused by Doctrine trying to persist the newly cloned Entity AND the one used as a template but I have no idea how I could (dis)prove that.
Any help would be greatly appreciated.
EDIT 1:
Thanks to @user2268997's comment, I now know that the second INSERT refers to the "template" circuit. Doctrine tries to update it as well, which is not what I want (I need the original data to be left unchanged). Any way I can tell Doctrine not to update the original entity ?
 
    