Doctrine 2 - ORM
  1. Doctrine 2 - ORM
  2. DDC-422

Unable to add entity in @ManyToMany association when owning entity is extended from another entity

    Details

    • Type: Bug Bug
    • Status: Closed
    • Priority: Blocker Blocker
    • Resolution: Fixed
    • Affects Version/s: 2.0-ALPHA4
    • Fix Version/s: 2.0-BETA1
    • Component/s: ORM
    • Security Level: All
    • Labels:
      None
    • Environment:
      PHP 5.3.2

      Description

      Dear developers,

      I'm not sure if i extend entities in right way but i found different behaviour in extended entity which won't process add in @ManyToMany association.
      My class are defined like this:

      /**
       * @Entity
       * @HasLifecycleCallbacks
       * @InheritanceType("JOINED")
       * @DiscriminatorColumn(name="discr", type="string")
       * @DiscriminatorMap({"guest" = "Shop_Data_Entity_Guest", "customer" = "Shop_Data_Entity_Customer"})
       */
      class Shop_Data_Entity_Guest extends Shop_Data_Entity_Abstract {
          public function __construct() {
              /* call parent construct with all parameters */
              call_user_func_array(array("parent","__construct"),func_get_args());
          }
      }
      
      /**
       * @Entity
       * @HasLifecycleCallbacks
       */
      class Shop_Data_Entity_Customer extends Shop_Data_Entity_Guest {
          /**
           * @ManyToMany(targetEntity="Shop_Data_Entity_Contact", cascade={"persist","remove"} )
           * @JoinTable(name="Shop_Data_Entity_Customer__homes",
           *      joinColumns={@JoinColumn(name="customer_id", referencedColumnName="id", onDelete="cascade" )},
           *      inverseJoinColumns={@JoinColumn(name="contact_id", referencedColumnName="id", onDelete="cascade" )}
           *      )
           */
          public $homes;
      
          public function __construct() {
              /* call parent construct with all parameters */
              call_user_func_array(array("parent","__construct"),func_get_args());
      
              $this->homes = new Shop_Data_Collection_Standard(); // this class only extends ArrayCollection
          }
      }
      

      When i fire this code:

              $q = $em->createQuery("select c from Shop_Data_Entity_Customer c");
              $q->setMaxResults(1);
              $customers = $q->getResult();
              
              $contact = new Shop_Data_Entity_Contact();
              $customers[0]->home->add($contact);
              $em->flush();
      

      There's no change in database.
      When i change definition od Guest class like this:

      /** @MappedSuperclass */
      class Shop_Data_Entity_Guest extends Shop_Data_Entity_Abstract {
          public function __construct() {
              /* call parent construct with all parameters */
              call_user_func_array(array("parent","__construct"),func_get_args());
          }
      }
      

      It start work and every firing of my code add one contact and association to my database. It causes problem only when owning entity is quered from database at first.

        Activity

        Hide
        Ondrej Sibrina added a comment -

        Thank you very much Hope this report was better than my first one.

        Show
        Ondrej Sibrina added a comment - Thank you very much Hope this report was better than my first one.
        Hide
        Roman S. Borschel added a comment -

        This is fixed now in trunk.

        Show
        Roman S. Borschel added a comment - This is fixed now in trunk.
        Hide
        Ondrej Sibrina added a comment -

        After using my patch i can't do $em->remove properly any other patch?

        Show
        Ondrej Sibrina added a comment - After using my patch i can't do $em->remove properly any other patch?
        Hide
        Ondrej Sibrina added a comment -

        To ensure i checkouted trunk version but it doesn't solve this problem.

        Andy

        Show
        Ondrej Sibrina added a comment - To ensure i checkouted trunk version but it doesn't solve this problem. Andy
        Hide
        Ondrej Sibrina added a comment -

        I tried to made patch by myself and it looks it start working. I'm not sure if this solution is proper. Andy

        from line 1731 of UnitOfWork.php

         if (isset($this->_identityMap[$class->name][$idHash])) {  // $$class->rootEntityName to $class->name
                    $entity = $this->_identityMap[$class->name][$idHash]; // $class->rootEntityName to $class->name
                    $oid = spl_object_hash($entity);
                    if ($entity instanceof Proxy && ! $entity->__isInitialized__) {
                        $entity->__isInitialized__ = true;
                        $overrideLocalValues = true;
                    } else {
                        $overrideLocalValues = isset($hints[Query::HINT_REFRESH]);
                    }
                } else {
                    //$entity = clone $class->prototype;
                    $entity = new $className;
                    $oid = spl_object_hash($entity);
                    $this->_entityIdentifiers[$oid] = $id;
                    $this->_entityStates[$oid] = self::STATE_MANAGED;
                    $this->_originalEntityData[$oid] = $data;
                    $this->_identityMap[$class->name][$idHash] = $entity; // $class->rootEntityName to $class->name
        
        Show
        Ondrej Sibrina added a comment - I tried to made patch by myself and it looks it start working. I'm not sure if this solution is proper. Andy from line 1731 of UnitOfWork.php if (isset($ this ->_identityMap[$class->name][$idHash])) { // $$class->rootEntityName to $class->name $entity = $ this ->_identityMap[$class->name][$idHash]; // $class->rootEntityName to $class->name $oid = spl_object_hash($entity); if ($entity instanceof Proxy && ! $entity->__isInitialized__) { $entity->__isInitialized__ = true ; $overrideLocalValues = true ; } else { $overrideLocalValues = isset($hints[Query::HINT_REFRESH]); } } else { //$entity = clone $class->prototype; $entity = new $className; $oid = spl_object_hash($entity); $ this ->_entityIdentifiers[$oid] = $id; $ this ->_entityStates[$oid] = self::STATE_MANAGED; $ this ->_originalEntityData[$oid] = $data; $ this ->_identityMap[$class->name][$idHash] = $entity; // $class->rootEntityName to $class->name
        Hide
        Ondrej Sibrina added a comment -

        I tried to debug by myself and i found that on line 411 in UnitOfWork.php is on flush in first example $class->associationMappings == null. When i change Shop_Data_Entity_Guest to /** @MappedSuperclass */ i can find $class->associationMappings on same line with some elements.

        Hope it help to fix it

        Andy

        Show
        Ondrej Sibrina added a comment - I tried to debug by myself and i found that on line 411 in UnitOfWork.php is on flush in first example $class->associationMappings == null. When i change Shop_Data_Entity_Guest to /** @MappedSuperclass */ i can find $class->associationMappings on same line with some elements. Hope it help to fix it Andy

          People

          • Assignee:
            Roman S. Borschel
            Reporter:
            Ondrej Sibrina
          • Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: