Skip to content

Loading…

DDC-2252: Trying to delete ManyToMany relatrionship with composite keys. #2952

Closed
doctrinebot opened this Issue · 13 comments

1 participant

@doctrinebot

Jira issue originally created by user yokoloko:

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.

@doctrinebot

Comment created by @ocramius:

[~yokoloko] is the schema validated by the cli tools?

@doctrinebot

Comment created by yokoloko:

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

@doctrinebot

Comment created by yokoloko:

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

@doctrinebot

Comment created by @ocramius:

[~yokoloko] can you abstract it away into a test?

@doctrinebot

Comment created by yokoloko:

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
@doctrinebot

Comment created by @ocramius:

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

@doctrinebot

Comment created by yokoloko:

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")
     *       }
     *   ....
@doctrinebot

Comment created by yokoloko:

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

@doctrinebot

Comment created by yokoloko:

Hi, any update on this issue?

@doctrinebot

Comment created by @ocramius:

[~yokoloko] will be checking this tomorrow

@doctrinebot

Comment created by yokoloko:

Everything ok with the check?

@doctrinebot

Comment created by @FabioBatSilva:

Fixed by : cef2089

@doctrinebot

Issue was closed with resolution "Fixed"

@doctrinebot doctrinebot added this to the 2.4 milestone
@doctrinebot doctrinebot closed this
@doctrinebot doctrinebot added the Bug label
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.