Doctrine 2 - ORM
  1. Doctrine 2 - ORM
  2. DDC-2624

ManyToManyPersister fails to handle cloned PeristentCollections

    Details

    • Type: Bug Bug
    • Status: Resolved
    • Priority: Critical Critical
    • Resolution: Fixed
    • Affects Version/s: Git Master
    • Fix Version/s: 2.5, 2.4.3
    • Component/s: ORM
    • Security Level: All
    • Labels:
      None

      Description

      I want to clone an entity and persist the clone. The entity itself works (if I reset the identifiers to null) but a M2M collection was first ignored since I only did a shallow copy. When I do a deep copy with the following, Doctrine throws the following exception:

      public function __clone()
      {
      if ($this->question_versions instanceof PersistentCollection)

      { $this->question_versions = clone $this->question_versions; }

      }

      Fatal error: Uncaught exception 'Doctrine\Common\Persistence\Mapping\MappingException' with message 'The class 'Doctrine\ORM\Persisters\ManyToManyPersister' was not found in the chain configured namespaces Foo\Entity' in /var/www/foo/vendor/doctrine/common/lib/Doctrine/Common/Persistence/Mapping/MappingException.php on line 37

      I've traced the error to the ManyToManyPersister class at the methods get

      {Delete,Insert}

      RowSQL where $coll->getOwner() is called which returns null because the owner is cleared when the collection is cloned. Therefore get_class does not work as expected under this circumstances.

      I've also tried to use $coll->getTypeClass() for $class at that point but this leads to other warnings ("array key not existing" and "spl_object hash got null") and finally an SQL exception because Doctrine is inserting null as one of the identifiers.

      There is a workaround for this issue but I think that this edge case should be handled too. The workaround is not to clone the collection itself but only copy the values with getValues() and let Doctrine convert it back to a collection.

        Activity

        Hide
        Martin Prebio added a comment -

        This issue may be related to DDC-2074

        Show
        Martin Prebio added a comment - This issue may be related to DDC-2074
        Hide
        Marcin Iwański added a comment -

        I have the same problem on v2.4.1 after cloning collections in __clone() method of the entity, so seems that DDC-2074 didnt` fix this case. But collection cloning is needed to properly manage cloned entity relationships.

        Show
        Marcin Iwański added a comment - I have the same problem on v2.4.1 after cloning collections in __clone() method of the entity, so seems that DDC-2074 didnt` fix this case. But collection cloning is needed to properly manage cloned entity relationships.
        Hide
        Martin Prebio added a comment -

        The getValues() workaround created some issues for us but I found another workaround. This one works for us for some time in a small to medium sized project where we heavily clone, detach and so on:

        __clone() {
        if ($this->m2mcoll instanceof PersistentCollection)

        { $this->m2mcoll = clone $this->m2mcoll; $this->m2mcoll->setOwner($this, $this->m2mcoll->getMapping()); }

        }

        The problem here is that this can not be put into the collection's clone method since it requires the entity object (which is $this).

        Show
        Martin Prebio added a comment - The getValues() workaround created some issues for us but I found another workaround. This one works for us for some time in a small to medium sized project where we heavily clone, detach and so on: __clone() { if ($this->m2mcoll instanceof PersistentCollection) { $this->m2mcoll = clone $this->m2mcoll; $this->m2mcoll->setOwner($this, $this->m2mcoll->getMapping()); } } The problem here is that this can not be put into the collection's clone method since it requires the entity object (which is $this).
        Hide
        Marcin Iwański added a comment -

        Thanks Martin for your help, your workaround seems to work well in my case. I don`t know yet if it has any drawbacks that may occur in longer time period. My general thought after dealing with entity cloning is that official manual should pay more attention to this topic, because I had to figure out most of the issues by myself.

        Show
        Marcin Iwański added a comment - Thanks Martin for your help, your workaround seems to work well in my case. I don`t know yet if it has any drawbacks that may occur in longer time period. My general thought after dealing with entity cloning is that official manual should pay more attention to this topic, because I had to figure out most of the issues by myself.
        Hide
        Martin Prebio added a comment -

        Yes, I've made the same experience regarding the documentation but still I haven't found time to contribute to it.
        Nevertheless if you run in any problems with my new workaround, please let me know of it. (I already spent some hours in the Doctrine code for some other issues)

        Show
        Martin Prebio added a comment - Yes, I've made the same experience regarding the documentation but still I haven't found time to contribute to it. Nevertheless if you run in any problems with my new workaround, please let me know of it. (I already spent some hours in the Doctrine code for some other issues)
        Show
        Benjamin Eberlei added a comment - Fixed in https://github.com/doctrine/doctrine2/commit/53a5a48aed7d87aa1533c0bcbd72e41b686527d8

          People

          • Assignee:
            Benjamin Eberlei
            Reporter:
            Martin Prebio
          • Votes:
            1 Vote for this issue
            Watchers:
            3 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: