Doctrine 2 - ORM
  1. Doctrine 2 - ORM
  2. DDC-2252

Trying to delete ManyToMany relatrionship with composite keys.

    Details

    • Type: Bug Bug
    • Status: Resolved
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: 2.1.7, 2.3.2
    • Fix Version/s: 2.4
    • Component/s: ORM
    • Security Level: All
    • Labels:
      None
    • Environment:
      Debian
      PHP 5.3.7

      Description

      Hi,

      When i try to delete some entities attached to an entity I've got the following message.

      My entity is specified as follow.

          /**
           * @ORM\Id
           * @ORM\ManyToOne(targetEntity="Entity\User\Account", inversedBy="memberships")
           * @ORM\JoinColumn(name="uid", referencedColumnName="uid")
           */
          protected $userAccount;
      
          /**
           * @ORM\Id
           * @ORM\ManyToOne(targetEntity="Entity\Merchant\Account")
           * @ORM\JoinColumn(name="mch_accountid", referencedColumnName="accountid")
           */
          protected $merchantAccount;
      
          /**
           * @ORM\Column(type="datetime", name="date")
           * @var datetime
           */
          protected $date;
      
          /**
           * @ORM\Column(type="boolean")
           * @var boolean
           */
          protected $administrator;
      
          /**
           * @ORM\ManyToMany(targetEntity="Entity\User\Privilege", indexBy="privilegeid")
           * @ORM\JoinTable(name="fsbackend.user_mch_account_privilege",
           *   joinColumns={
           *       @ORM\JoinColumn(name="mch_accountid", referencedColumnName="mch_accountid"),
           *       @ORM\JoinColumn(name="uid", referencedColumnName="uid")
           *   },
           *   inverseJoinColumns={
           *       @ORM\JoinColumn(name="privilegeid", referencedColumnName="privilegeid")
           *   }
           * )
           */
          protected $privileges;
      

      I delete the related entities

          $membership->getPrivileges()->clear();
      
          $this->_em->persist($userAccount);
          $this->_em->flush();
      

      I tried on doctrine 2.1.7 and the last doctrine version and same thing happens.

      Please find attached the error log.

      1. AdvancedAssociationTest.php
        4 kB
        Jeremie Tom tom
      2. jira-doctrine.txt
        9 kB
        Jeremie Tom tom
      3. patch.diff
        1 kB
        Jeremie Tom tom

        Activity

        Jeremie Tom tom created issue -
        Hide
        Marco Pivetta added a comment -

        Jeremie Tom tom is the schema validated by the cli tools?

        Show
        Marco Pivetta added a comment - Jeremie Tom tom is the schema validated by the cli tools?
        Hide
        Jeremie Tom tom added a comment -

        Yes it's validated by the cli tools, if you are talking about the orm:validate-schema command.

        Show
        Jeremie Tom tom added a comment - Yes it's validated by the cli tools, if you are talking about the orm:validate-schema command.
        Hide
        Jeremie Tom tom added a comment -

        I think the problem is that my @Id are entities.

        Show
        Jeremie Tom tom added a comment - I think the problem is that my @Id are entities.
        Hide
        Marco Pivetta added a comment -

        Jeremie Tom tom can you abstract it away into a test?

        Show
        Marco Pivetta added a comment - Jeremie Tom tom can you abstract it away into a test?
        Marco Pivetta made changes -
        Field Original Value New Value
        Description Hi,

        When i try to delete some entities attached to an entity I've got the following message.

        My entity is specified as follow.

            /**
             * @ORM\Id
             * @ORM\ManyToOne(targetEntity="Entity\User\Account", inversedBy="memberships")
             * @ORM\JoinColumn(name="uid", referencedColumnName="uid")
             */
            protected $userAccount;

            /**
             * @ORM\Id
             * @ORM\ManyToOne(targetEntity="Entity\Merchant\Account")
             * @ORM\JoinColumn(name="mch_accountid", referencedColumnName="accountid")
             */
            protected $merchantAccount;

            /**
             * @ORM\Column(type="datetime", name="date")
             * @var datetime
             */
            protected $date;

            /**
             * @ORM\Column(type="boolean")
             * @var boolean
             */
            protected $administrator;

            /**
             * @ORM\ManyToMany(targetEntity="Entity\User\Privilege", indexBy="privilegeid")
             * @ORM\JoinTable(name="fsbackend.user_mch_account_privilege",
             * joinColumns={
             * @ORM\JoinColumn(name="mch_accountid", referencedColumnName="mch_accountid"),
             * @ORM\JoinColumn(name="uid", referencedColumnName="uid")
             * },
             * inverseJoinColumns={
             * @ORM\JoinColumn(name="privilegeid", referencedColumnName="privilegeid")
             * }
             * )
             */
            protected $privileges;

        I delete the related entities

            $membership->getPrivileges()->clear();

            $this->_em->persist($userAccount);
            $this->_em->flush();

        I tried on doctrine 2.1.7 and the last doctrine version and same thing happens.

        Please find attached the error log.
        Hi,

        When i try to delete some entities attached to an entity I've got the following message.

        My entity is specified as follow.

        {code}
            /**
             * @ORM\Id
             * @ORM\ManyToOne(targetEntity="Entity\User\Account", inversedBy="memberships")
             * @ORM\JoinColumn(name="uid", referencedColumnName="uid")
             */
            protected $userAccount;

            /**
             * @ORM\Id
             * @ORM\ManyToOne(targetEntity="Entity\Merchant\Account")
             * @ORM\JoinColumn(name="mch_accountid", referencedColumnName="accountid")
             */
            protected $merchantAccount;

            /**
             * @ORM\Column(type="datetime", name="date")
             * @var datetime
             */
            protected $date;

            /**
             * @ORM\Column(type="boolean")
             * @var boolean
             */
            protected $administrator;

            /**
             * @ORM\ManyToMany(targetEntity="Entity\User\Privilege", indexBy="privilegeid")
             * @ORM\JoinTable(name="fsbackend.user_mch_account_privilege",
             * joinColumns={
             * @ORM\JoinColumn(name="mch_accountid", referencedColumnName="mch_accountid"),
             * @ORM\JoinColumn(name="uid", referencedColumnName="uid")
             * },
             * inverseJoinColumns={
             * @ORM\JoinColumn(name="privilegeid", referencedColumnName="privilegeid")
             * }
             * )
             */
            protected $privileges;
        {code}

        I delete the related entities

        {code}
            $membership->getPrivileges()->clear();

            $this->_em->persist($userAccount);
            $this->_em->flush();
        {code}

        I tried on doctrine 2.1.7 and the last doctrine version and same thing happens.

        Please find attached the error log.
        Hide
        Jeremie Tom tom added a comment - - edited

        Here is my test case.

        I put it IN Doctrine\Test\ORMJT.
        I don't really know if you need something else, please let met know.

        <?php
        
        namespace Doctrine\Tests\ORMJT;
        
        use Doctrine\ORM\Query;
        use Doctrine\Common\Collections\ArrayCollection;
        
        require_once __DIR__ . '/../TestInit.php';
        
        /**
         * Functional tests for the Single Table Inheritance mapping strategy.
         *
         * @author robo
         */
        class AdvancedAssociationTest extends \Doctrine\Tests\OrmFunctionalTestCase
        {
            protected function setUp() {
                parent::setUp();
                try {
                    $this->_schemaTool->createSchema(array(
                        $this->_em->getClassMetadata('Doctrine\Tests\ORMJT\User'),
                        $this->_em->getClassMetadata('Doctrine\Tests\ORMJT\MerchantAccount'),
                        $this->_em->getClassMetadata('Doctrine\Tests\ORMJT\Membership'),
                        $this->_em->getClassMetadata('Doctrine\Tests\ORMJT\Privilege')
                    ));
                } catch (\Exception $e) {
                    // Swallow all exceptions. We do not test the schema tool here.
                }
            }
        
            public function testIssue()
            {
                $user = new User;
                $merchantAccount = new MerchantAccount;
                $privilege = new Privilege;
                $membership = new Membership($user, $merchantAccount);
                $membership->addPrivilege($privilege);
        
                $this->_em->persist($user);
                $this->_em->persist($merchantAccount);
                $this->_em->persist($privilege);
                $this->_em->flush();
        
                $this->_em->persist($membership);
                $this->_em->flush();
        
                $membership->getPrivileges()->clear();
        
                $this->_em->flush();
        
                // Never reached
                $this->assertTrue(true);
            }
        }
        
        
        /**
         * @Entity
         * @Table(name="mch_account")
         */
        class MerchantAccount
        {
            /**
             * @Id @GeneratedValue
             * @Column(type="bigint")
             * @var bigint $accountid
             */
            protected $accountid;
        }
        
        /**
         * @Entity(repositoryClass="Repository\User\PrivilegeRepository")
         * @Table(name="acl_privilege")
         */
        class Privilege
        {
            /**
             * @Id @GeneratedValue
             * @Column(type="bigint")
             * @var integer
             */
            protected $privilegeid;
        }
        
        /**
         * @Entity
         * @Table(name="user_account")
         */
        class User {
            /**
             * @Id @GeneratedValue
             * @Column(type="bigint")
             * @var integer
             */
            protected $uid;
        
            /**
             * @OneToMany(targetEntity="Membership", mappedBy="userAccount", cascade={"persist"})
             * @JoinColumn(name="uid", referencedColumnName="uid")
             */
            protected $memberships;
        
            public function __construct()
            {
                $this->memberships = new ArrayCollection;
            }
        
            public function getMemberships()
            {
                return $this->memberships;
            }
        
            public function addMembership(Membership $membership)
            {
                $this->memberships[] = $membership;
            }
        }
        
        /**
         * @Entity
         * @Table(name="mch_account_member")
         * @HasLifecycleCallbacks
         */
        class Membership
        {
            /**
             * @Id
             * @ManyToOne(targetEntity="User", inversedBy="memberships")
             * @JoinColumn(name="uid", referencedColumnName="uid")
             */
            protected $userAccount;
        
            /**
             * @Id
             * @ManyToOne(targetEntity="MerchantAccount")
             * @JoinColumn(name="mch_accountid", referencedColumnName="accountid")
             */
            protected $merchantAccount;
        
            /**
             * @ManyToMany(targetEntity="Privilege", indexBy="privilegeid")
             * @JoinTable(name="user_mch_account_privilege",
             *   joinColumns={
             *       @JoinColumn(name="mch_accountid", referencedColumnName="mch_accountid"),
             *       @JoinColumn(name="uid", referencedColumnName="uid")
             *   },
             *   inverseJoinColumns={
             *       @JoinColumn(name="privilegeid", referencedColumnName="privilegeid")
             *   }
             * )
             */
            protected $privileges;
        
            public function __construct(User $user, MerchantAccount $merchantAccount)
            {
                $this->userAccount = $user;
                $this->merchantAccount = $merchantAccount;
                $this->privileges = new ArrayCollection();
            }
        
            public function addPrivilege($privilege)
            {
                $this->privileges[] = $privilege;
            }
        
            public function getPrivileges()
            {
                return $this->privileges;
            }
        }
        

        And i've got the following error

        1) Doctrine\Tests\ORMJT\AdvancedAssociationTest::testIssue
        Exception: [PHPUnit_Framework_Error_Notice] Undefined index: mch_accountid
        
        Show
        Jeremie Tom tom added a comment - - edited Here is my test case. I put it IN Doctrine\Test\ORMJT. I don't really know if you need something else, please let met know. <?php namespace Doctrine\Tests\ORMJT; use Doctrine\ORM\Query; use Doctrine\Common\Collections\ArrayCollection; require_once __DIR__ . '/../TestInit.php'; /** * Functional tests for the Single Table Inheritance mapping strategy. * * @author robo */ class AdvancedAssociationTest extends \Doctrine\Tests\OrmFunctionalTestCase { protected function setUp() { parent::setUp(); try { $ this ->_schemaTool->createSchema(array( $ this ->_em->getClassMetadata('Doctrine\Tests\ORMJT\User'), $ this ->_em->getClassMetadata('Doctrine\Tests\ORMJT\MerchantAccount'), $ this ->_em->getClassMetadata('Doctrine\Tests\ORMJT\Membership'), $ this ->_em->getClassMetadata('Doctrine\Tests\ORMJT\Privilege') )); } catch (\Exception $e) { // Swallow all exceptions. We do not test the schema tool here. } } public function testIssue() { $user = new User; $merchantAccount = new MerchantAccount; $privilege = new Privilege; $membership = new Membership($user, $merchantAccount); $membership->addPrivilege($privilege); $ this ->_em->persist($user); $ this ->_em->persist($merchantAccount); $ this ->_em->persist($privilege); $ this ->_em->flush(); $ this ->_em->persist($membership); $ this ->_em->flush(); $membership->getPrivileges()->clear(); $ this ->_em->flush(); // Never reached $ this ->assertTrue( true ); } } /** * @Entity * @Table(name= "mch_account" ) */ class MerchantAccount { /** * @Id @GeneratedValue * @Column(type= "bigint" ) * @ var bigint $accountid */ protected $accountid; } /** * @Entity(repositoryClass= "Repository\User\PrivilegeRepository" ) * @Table(name= "acl_privilege" ) */ class Privilege { /** * @Id @GeneratedValue * @Column(type= "bigint" ) * @ var integer */ protected $privilegeid; } /** * @Entity * @Table(name= "user_account" ) */ class User { /** * @Id @GeneratedValue * @Column(type= "bigint" ) * @ var integer */ protected $uid; /** * @OneToMany(targetEntity= "Membership" , mappedBy= "userAccount" , cascade={ "persist" }) * @JoinColumn(name= "uid" , referencedColumnName= "uid" ) */ protected $memberships; public function __construct() { $ this ->memberships = new ArrayCollection; } public function getMemberships() { return $ this ->memberships; } public function addMembership(Membership $membership) { $ this ->memberships[] = $membership; } } /** * @Entity * @Table(name= "mch_account_member" ) * @HasLifecycleCallbacks */ class Membership { /** * @Id * @ManyToOne(targetEntity= "User" , inversedBy= "memberships" ) * @JoinColumn(name= "uid" , referencedColumnName= "uid" ) */ protected $userAccount; /** * @Id * @ManyToOne(targetEntity= "MerchantAccount" ) * @JoinColumn(name= "mch_accountid" , referencedColumnName= "accountid" ) */ protected $merchantAccount; /** * @ManyToMany(targetEntity= "Privilege" , indexBy= "privilegeid" ) * @JoinTable(name= "user_mch_account_privilege" , * joinColumns={ * @JoinColumn(name= "mch_accountid" , referencedColumnName= "mch_accountid" ), * @JoinColumn(name= "uid" , referencedColumnName= "uid" ) * }, * inverseJoinColumns={ * @JoinColumn(name= "privilegeid" , referencedColumnName= "privilegeid" ) * } * ) */ protected $privileges; public function __construct(User $user, MerchantAccount $merchantAccount) { $ this ->userAccount = $user; $ this ->merchantAccount = $merchantAccount; $ this ->privileges = new ArrayCollection(); } public function addPrivilege($privilege) { $ this ->privileges[] = $privilege; } public function getPrivileges() { return $ this ->privileges; } } And i've got the following error 1) Doctrine\Tests\ORMJT\AdvancedAssociationTest::testIssue Exception: [PHPUnit_Framework_Error_Notice] Undefined index: mch_accountid
        Jeremie Tom tom made changes -
        Attachment AdvancedAssociationTest.php [ 11375 ]
        Hide
        Marco Pivetta added a comment -

        Thank you so far, this makes it much easier to work with it!

        Show
        Marco Pivetta added a comment - Thank you so far, this makes it much easier to work with it!
        Hide
        Jeremie Tom tom added a comment - - edited

        Interesting fact, if I only have one column in my jointable it works fine.

        eg.

        class Membership
             *   ....
             *   @JoinTable(name="user_mch_account_privilege",
             *       joinColumns={
             *           @JoinColumn(name="uid", referencedColumnName="uid")
             *       }
             *   ....
        
        Show
        Jeremie Tom tom added a comment - - edited Interesting fact, if I only have one column in my jointable it works fine. eg. class Membership * .... * @JoinTable(name= "user_mch_account_privilege" , * joinColumns={ * @JoinColumn(name= "uid" , referencedColumnName= "uid" ) * } * ....
        Hide
        Jeremie Tom tom added a comment -

        Ok here is my two cents solution. passes the tests.

        Show
        Jeremie Tom tom added a comment - Ok here is my two cents solution. passes the tests.
        Jeremie Tom tom made changes -
        Attachment patch.diff [ 11377 ]
        Hide
        Jeremie Tom tom added a comment -

        Hi, any update on this issue?

        Show
        Jeremie Tom tom added a comment - Hi, any update on this issue?
        Hide
        Marco Pivetta added a comment -

        Jeremie Tom tom will be checking this tomorrow

        Show
        Marco Pivetta added a comment - Jeremie Tom tom will be checking this tomorrow
        Hide
        Jeremie Tom tom added a comment -

        Everything ok with the check?

        Show
        Jeremie Tom tom added a comment - Everything ok with the check?
        Fabio B. Silva made changes -
        Assignee Benjamin Eberlei [ beberlei ] Fabio B. Silva [ fabio.bat.silva ]
        Show
        Fabio B. Silva added a comment - Fixed by : https://github.com/doctrine/doctrine2/commit/cef20890dc75c11880827226e25f3fc6d5d66127
        Fabio B. Silva made changes -
        Status Open [ 1 ] Resolved [ 5 ]
        Fix Version/s 2.4 [ 10321 ]
        Resolution Fixed [ 1 ]

        This list may be incomplete, as errors occurred whilst retrieving source from linked applications:

        • Request to http://www.doctrine-project.org/fisheye/ failed: Error in remote call to 'FishEye 0 (http://www.doctrine-project.org/fisheye/)' (http://www.doctrine-project.org/fisheye) [AbstractRestCommand{path='/rest-service-fe/search-v1/crossRepositoryQuery', params={query=DDC-2252, expand=changesets[0:20].revisions[0:29],reviews}, methodType=GET}] : Received status code 503 (Service Temporarily Unavailable)

          People

          • Assignee:
            Fabio B. Silva
            Reporter:
            Jeremie Tom tom
          • Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: