如何在双向一对一继承中使用Doctrine

时间:2019-05-14 12:10:57

标签: php doctrine prepared-statement

我有一个对象MainClass,其中包含另一个对象SubClass,并且我正在使用双向一对一的对象。 SubClass有多个版本,它们是使用“类类型继承”建模的。 ERD如下所示。请注意,如果我做错了什么,或者Doctrine中是否有错误,但是在添加记录时,Doctrine不会为查询提供正确数量的参数。 enter image description here

我的实体定义如下(SubClassType2不相关且未显示)

<?php
use Doctrine\ORM\Mapping as ORM;

/**
 * MainClass
 *
 * @Table(name="mainClass")
 * @Entity
 */
class MainClass
{
    /**
     * @var int
     *
     * @Column(name="id", type="integer")
     * @Id
     * @GeneratedValue(strategy="IDENTITY")
     */
    protected $id;

    /** @Column(type="string") */
    protected $name;

    /**
     * @var \SubClass
     *
     * @OneToOne(targetEntity="SubClass", mappedBy="mainClass", cascade={"persist","remove"}, orphanRemoval=true)
     */
    protected $subClass;

    public function getId()
    {
        return $this->id;
    }

    public function getName()
    {
        return $this->name;
    }
    public function setName($name)
    {
        $this->name = $name;
    }

    public function setSubClass(\SubClass $subClass)
    {
        $this->subClass = $subClass;

        return $this;
    }

    public function getSubClass()
    {
        return $this->subClass;
    }
}

<?php
use Doctrine\ORM\Mapping as ORM;

/**
 * SubClass
 *
 * @Table(name="subClass")
 * @InheritanceType("JOINED")
 * @DiscriminatorColumn(name="discriminator", type="string", length=32)
 * @DiscriminatorMap({"subClassType1" = "SubClassType1", "subClassType2" = "SubClassType2"})
 * @Entity
 */
abstract class SubClass
{
    /**
     * @var \MainClass
     *
     * @Id
     * @GeneratedValue(strategy="NONE")
     * @OneToOne(targetEntity="MainClass", inversedBy="subClass")
     * @JoinColumns({
     *   @JoinColumn(name="id", referencedColumnName="id", onDelete="CASCADE")
     * })
     */
    protected $mainClass;

    /** @Column(type="string") */
    protected $someCommonProperty;


    public function setMainClass(\MainClass $mainClass)
    {
        $mainClass->setSubClass($this);
        $this->mainClass = $mainClass;

        return $this;
    }

    public function getMainClass()
    {
        return $this->mainClass;
    }

    public function getId()
    {
        return $this->id;
    }

    public function getSomeCommonProperty()
    {
        return $this->someCommonProperty;
    }
    public function setSomeCommonProperty($someCommonProperty)
    {
        $this->someCommonProperty = $someCommonProperty;
    }
}

<?php
use Doctrine\ORM\Mapping as ORM;

/**
 * SubClassType1
 *
 * @Table(name="subclassType1")
 * @Entity
 */
class SubClassType1 extends SubClass
{

    /** @Column(type="string") */
    protected $someIndividualProperty;

    public function getSomeIndividualProperty()
    {
        return $this->someIndividualProperty;
    }
    public function setSomeIndividualProperty($someIndividualProperty)
    {
        $this->someIndividualProperty = $someIndividualProperty;
    }
}

我尝试如下添加新记录。

<?php
ini_set('display_errors', 1);

require_once "bootstrap.php";

$mainClass = new MainClass();
$mainClass->setName('MainClassName');
$subClass=new SubClassType1();
$subClass->setSomeCommonProperty('SomeCommonProperty');
$subClass->setSomeIndividualProperty('SomeIndividualProperty');
$subClass->setMainClass($mainClass);

$entityManager->getConnection()
  ->getConfiguration()
  ->setSQLLogger(new \Doctrine\DBAL\Logging\EchoSQLLogger())
;

$entityManager->persist($mainClass);
$entityManager->flush();

输出为:

[michael@devserver testing]$ php create.php
"START TRANSACTION"
INSERT INTO mainClass (name) VALUES (?)
array(1) {
  [1]=>
  string(13) "MainClassName"
}
array(1) {
  [1]=>
  string(6) "string"
}
INSERT INTO subClass (someCommonProperty, id, discriminator) VALUES (?, ?, ?)
array(3) {
  [1]=>
  string(18) "SomeCommonProperty"
  [2]=>
  int(7)
  [3]=>
  string(13) "subClassType1"
}
array(3) {
  [1]=>
  string(6) "string"
  [2]=>
  string(7) "integer"
  [3]=>
  string(6) "string"
}

Notice: Undefined index: 000000000744ff62000000006b73da3c in /var/www/testing/vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php on line 2995
INSERT INTO subclassType1 (id, someIndividualProperty) VALUES (?, ?)
array(1) {
  [1]=>
  string(22) "SomeIndividualProperty"
}
array(1) {
  [1]=>
  string(6) "string"
}
"ROLLBACK"

Fatal error: Uncaught PDOException: SQLSTATE[HY093]: Invalid parameter number: number of bound variables does not match number of tokens in /var/www/testing/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOStatement.php:117
Stack trace:
#0 /var/www/testing/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOStatement.php(117): PDOStatement->execute(NULL)
#1 /var/www/testing/vendor/doctrine/dbal/lib/Doctrine/DBAL/Statement.php(153): Doctrine\DBAL\Driver\PDOStatement->execute(NULL)
#2 /var/www/testing/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/Entity/JoinedSubclassPersister.php(213): Doctrine\DBAL\Statement->execute()
#3 /var/www/testing/vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php(1073): Doctrine\ORM\Persisters\Entity\JoinedSubclassPersister->executeInserts()
#4 /var/www/testing/vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php(386): Doctrine\ORM\UnitOfWork->executeInserts(Object(Doctrine\ORM\Mapping\ClassMetadata))
#5 /var/www/testing/vendor/doctrine/orm/lib/Doctrine/ORM/EntityManager.php(359): Do in /var/www/testing/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractMySQLDriver.php on line 106
[michael@devserver testing]$

如图所示,准备好的语句INSERT INTO subclassType1 (id, someIndividualProperty) VALUES (?, ?)正在传递array(1) {[1] => string(22) "SomeIndividualProperty"}。您可能已经注意到,我的财产是受保护的,而不是私有的,这只是希望它可以解决问题,但没有这样做。我还对生命周期回调进行了试验,发现该错误发生在MainClass的PostPersist和SubClass的PostPersist之间,但是,不确定是否有帮助。

如何创建新记录?

0 个答案:

没有答案