PHP 5.6, Doctrine ORM 2.5.5.
Hello! I got trouble with the inserting/updating Entity which has OneToMany two-columns self-referencing association.
I have table Shop with shops and table Group with groups. Every shop has its own set of groups. Every group can has one parent group within the same shop.
Model:
<?php
/**
* @Entity
*/
class Shop
{
/**
* @Id @Column(type="integer") @GeneratedValue
*/
private $id;
/**
* @Column(type="string")
*/
private $name;
}
```php
/**
/**
/**
public function __construct(Shop $shop, $id, Group $parent = null)
{
$this->shop = $shop;
$this->id = $id;
$this->parent = $parent;
}
}
Works fine when I insert with the `$parent` specified, but get error, if `$parent=null` (case of a root group):
```php
<?php
$shop = $em->find("Shop", 1); // surely existing Shop
$group = new Group($shop, 'some_id', null);
$em->persist($group);
$em->flush();
An exception occurred while executing 'INSERT INTO
Group(id, shop, parent) VALUES (?, ?, ?)' with params ["some_id", null, null]: SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'shop' cannot be null
I can't understand what is wrong. Why shop=null? I'm sure that $shop is passing correct to the __construct() (checked it).
Same thing if I try to update an existing row by setting $parent=null - Doctrine 2 will try to set shop=null too.
Please help. Thanks in advance.
@mittahru weird edge case, but can you eventually abstract it into a test case? See https://github.com/doctrine/doctrine2/tree/d3f6c5ec70aac4b029a4b61ecf1e2ba61a1a4a6d/tests/Doctrine/Tests/ORM/Functional/Ticket for examples.
@Ocramius, you mean this?
DDC6117Test.php
<?php
namespace Doctrine\Tests\ORM\Functional\Ticket;
class DDC6117Test extends \Doctrine\Tests\OrmFunctionalTestCase
{
public function setUp()
{
parent::setUp();
parent::setUpEntitySchema(array
(
__NAMESPACE__ . '\DDC6117Shop',
__NAMESPACE__ . '\DDC6117Group',
));
}
/**
* @group DDC-6117
*/
public function addRootGroup()
{
$shop = new DDC6117Shop();
$this->_em->persist($shop);
$this->_em->flush();
var_dump($shop->getId());
$group = new DDC6117Group($shop, 'test-group-id', null);
$this->_em->persist($group);
$this->_em->flush();
}
}
/**
* @Entity
* @Table(name="DDC6117Shop")
*/
class DDC6117Shop
{
/**
* @Id @Column(type="integer") @GeneratedValue
*/
private $id;
public function getId()
{
return $this->id;
}
}
/**
* @Entity
* @Table(name="DDC6117Group")
*/
class DDC6117Group
{
/**
* @Id @ManyToOne(targetEntity="DDC6117Shop")
* @JoinColumn(name="shop",referencedColumnName="id")
*/
private $shop;
/**
* @Id @Column(type="string")
*/
private $id;
/**
* @ManyToOne(targetEntity="DDC6117Group")
* @JoinColumns
* (
* @JoinColumn(name="shop",referencedColumnName="shop"),
* @JoinColumn(name="parent",referencedColumnName="id"),
* )
*/
private $parent;
public function __construct(DDC6117Shop $shop, $id, DDC6117Group $parent = null)
{
$this->shop = $shop;
$this->id = $id;
$this->parent = $parent;
}
}
Perfect, thanks!
On 5 Nov 2016 17:39, "Dmitry Pozdeiev" [email protected] wrote:
@Ocramius https://github.com/Ocramius, you mean this?
DDC6117Test.php
namespace Doctrine\Tests\ORM\Functional\Ticket;
class DDC6117Test extends \Doctrine\Tests\OrmFunctionalTestCase
{
public function setUp()
{
parent::setUp();
parent::setUpEntitySchema(array
(
NAMESPACE . '\DDC6117Shop',
NAMESPACE . '\DDC6117Group',
));
}
/**
* @group DDC-6117
*/
public function addRootGroup()
{
$shop = new DDC6117Shop();
$this->_em->persist($shop);
$this->_em->flush();
var_dump($shop->getId());
$group = new DDC6117Group($shop, 'test-group-id', null);
$this->_em->persist($group);
$this->_em->flush();
}
}/**
- @Entity
- @Table(name="DDC6117Shop")
_/
class DDC6117Shop
{
/_*
- @Id @Column(type="integer") @GeneratedValue
*/
private $id;
public function getId()
{
return $this->id;
}
}/**
- @Entity
- @Table(name="DDC6117Group")
_/
class DDC6117Group
{
/_*
- @Id @ManyToOne(targetEntity="DDC6117Shop")
- @JoinColumn(name="shop",referencedColumnName="id")
*/
private $shop;
/**
- @Id @Column(type="string")
*/
private $id;/**
- @ManyToOne(targetEntity="DDC6117Group")
- @JoinColumns
- (
- @JoinColumn(name="shop",referencedColumnName="shop"),
- @JoinColumn(name="parent",referencedColumnName="id"),
- )
*/
private $parent;public function __construct(DDC6117Shop $shop, $id, DDC6117Group $parent = null)
{
$this->shop = $shop;
$this->id = $id;
$this->parent = $parent;
}
}—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/doctrine/doctrine2/issues/6117#issuecomment-258623237,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AAJakACHrQdMZfDz--5cel0kF_U3RO_aks5q7LFYgaJpZM4KqE3I
.
This issue still missing tests?
No, lemme remove the label. It wasn't picked up by anyone though.
@mittahru the problem is happening because your mapping is incorrect... since $parent is a nullable field the join columns should also be nullable (and they should not use the same columns of the entity itself), like:
/**
* @Entity
*/
class DDC6117Group
{
/**
* @Id @ManyToOne(targetEntity=DDC6117Shop::class)
* @JoinColumn(name="shop",referencedColumnName="id")
*/
public $shop;
/**
* @Id @Column(type="string")
*/
public $id;
/**
* @ManyToOne(targetEntity=DDC6117Group::class)
* @JoinColumns(
* {
* @JoinColumn(name="parent_shop", referencedColumnName="shop", nullable=true),
* @JoinColumn(name="parent_id", referencedColumnName="id", nullable=true)
* }
* )
*/
public $parent;
public function __construct(DDC6117Shop $shop, string $id, DDC6117Group $parent = null)
{
$this->shop = $shop;
$this->id = $id;
$this->parent = $parent;
}
}
With mapping above the test bellow passes with no issues:
/**
* @group 6117
*/
public function testAddRootGroup() : void
{
$shop = new DDC6117Shop();
$group = new DDC6117Group($shop, 'test-group-id', null);
$group2 = new DDC6117Group($shop, 'test-group2-id', $group);
$this->_em->persist($shop);
$this->_em->flush();
$this->_em->persist($group);
$this->_em->persist($group2);
$this->_em->flush();
self::assertSame($group2, $this->_em->getRepository(DDC6117Group::class)->findOneBy(['parent' => $group]));
}
I'll close this ticket as Invalid due to the given explanation.
@lcobucci thanks a lot!
Most helpful comment
@mittahru the problem is happening because your mapping is incorrect... since
$parentis a nullable field the join columns should also be nullable (and they should not use the same columns of the entity itself), like:With mapping above the test bellow passes with no issues: