У меня есть объект MainClass
, который содержит другой объект SubClass
, и я использую двунаправленный один-к-одному.Существует несколько версий SubClass
, которые смоделированы с использованием наследования типов классов.ERD показано ниже.Обратите внимание, что если я делаю что-то не так или есть ошибка в Doctrine, но при добавлении записи Doctrine не предоставляет правильное количество параметров для запроса.
Мои сущности определены следующим образом (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"}
.Возможно, вы заметили, что мои свойства защищены, а не частные, и это была всего лишь надежда, что это решит проблему, но не сделали этого.Я также экспериментировал с обратными вызовами жизненного цикла и обнаружил, что ошибка возникает между PostCersist MainClass и PostPersist SubClass, однако я не уверен, может ли это чем-то помочь.
Как можно создать новую запись?