I have a entity, BaseValue
, as a mapped superclass. A second entity, called Field
, is mapping this superclass.
I can store it and the values of the child classes from BaseValue
are stored in the correct table.
But if I try to read them, I got this error:
An exception occurred while executing 'SELECT t0.id AS id_1, t0.iid AS iid_2, t0.lid AS lid_3, t5.fid AS fid_4 FROM fields t0 LEFT JOIN BaseValue t5 ON t5.fid = t0.id WHERE t0.iid = ?' with params [1]:
SQLSTATE[42S02]: Base table or view not found: 1146 Table 'testproject.BaseValue' doesn't exist
Of course it does not exist, because it has no values. These are all stored to the tables of child entities.
The derived entity (mapped superclass):
<?php
namespace my\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
/** @ORM\MappedSuperclass */
class BaseValue
{
/**
* @var int
*
* @ORM\Id
* @ORM\Column(name="id", type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* @ORM\OneToOne(targetEntity="Field", inversedBy="value")
* @ORM\JoinColumn(name="fid", referencedColumnName="id")
**/
private $field;
/**
* @return int
*/
public function getId()
{
return $this->id;
}
/**
* @param int $id
*/
public function setId($id)
{
$this->id = $id;
}
public function setField($field){
$this->field=$field;
}
public function getField(){
return $this->field;
}
}
One of the childs:
<?php
namespace my\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
/**
* Value
* @package my\Entity
*
* @ORM\Entity
* @ORM\Table(name="integers")
*/
class Integer extends BaseValue
{
/**
* @var integer
*
* @ORM\Column(name="value", type="integer", nullable=true)
*/
protected $value;
/**
* @return string
*/
public function getValue()
{
return $this->value;
}
/**
* @param string $value
*/
public function setValue($value)
{
$this->value = $value;
}
}
The entity which has a relation to one of the childs:
<?php
namespace my\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Field
* @package my\Entity
*
* @ORM\Entity
* @ORM\Table(name="fields")
*/
class Field
{
/**
* @var int
*
* @ORM\Id
* @ORM\Column(name="id", type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* @var
* @ORM\ManyToOne(targetEntity="Item", inversedBy="fields")
* @ORM\JoinColumn(name="iid", referencedColumnName="id")
*/
protected $item;
/**
* @var
* @ORM\ManyToOne(targetEntity="Label", inversedBy="fields")
* @ORM\JoinColumn(name="lid", referencedColumnName="id")
*/
protected $label;
/**
* @ORM\OneToOne(targetEntity="BaseValue", mappedBy="field", cascade="persist")
**/
private $value;
protected $temp;
public function __construct($label=null, $value=null){
$this->setLabel($label);
$this->setValue($value);
}
public function setItem(Item $item = null){
$this->item = $item;
}
public function getItem(){
return $this->item;
}
/**
* @return int
*/
public function getId()
{
return $this->id;
}
/**
* @return string
*/
public function getValue()
{
return $this->value->getValue();
}
/**
* @param string $value
*/
public function setValue($value)
{
$sType = gettype($value);
switch($sType){
case 'boolean':
$this->setBooleanValue($value);
break;
case 'integer':
$this->setIntegerValue($value);
break;
case 'double':
$this->setDoubleValue($value);
break;
case 'string':
$this->setStringValue($value);
break;
case 'array':
$this->setArrayValue($value);
break;
case 'object':
$this->setObjectValue($value);
break;
case 'resource':
$this->setResourceValue($value);
break;
case 'NULL':
$this->setNullValue();
break;
default:
break;
}
}
protected function setBooleanValue($value){
$this->value = new Boolean($value);
$this->value->setValue($value);
$this->value->setField($this);
}
protected function setIntegerValue($value){
$this->value = new Integer($value);
$this->value->setValue($value);
$this->value->setField($this);
}
protected function setDoubleValue($value){
$this->value = new Double($value);
$this->value->setValue($value);
$this->value->setField($this);
}
protected function setStringValue($value){
$this->value = new String($value);
$this->value->setValue($value);
$this->value->setField($this);
}
protected function setArrayValue($value){
throw new \Exception ('arrays are currently not working');
}
protected function setObjectValue($value){
throw new \Exception ('objects are currently not working');
}
protected function setResourceValue($value){
throw new \Exception ('resources are currently not working');
}
protected function setNullValue(){
}
public function setLabel($label){
if( is_object($label) && 'my\Entity\Label' == get_class($label)){
$this->label = $label;
$this->temp=null;
}else{
$this->temp = $label;
}
}
public function getLabel(){
if( $this->label !== null){
return $this->label;
} else {
return $this->temp;
}
}
}
The controller, to read:
public function testRead()
{
/* @var \my\Entity\Item $item */
/* @var \my\Entity\Collection $collection */
$item = $this->getEntityManager()->getRepository('my\Entity\Item')->findOneBy(array('id'=>'1'));
$this->sDesktop .= 'Item ID = ' . $item->getId();
$collection = $item->getCollection();
$this->sDesktop .= '<br>Collection = ' . $collection->getName();
$this->sDesktop .= '<br>Directive = ' . $collection->getDirective();
count($item->getFields());
}
And here it crashes with:
Doctrine\DBAL\Exception\TableNotFoundException
Datei:
/var/www/html/myproject/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractMySQLDriver.php:53Meldung:
An exception occurred while executing 'SELECT t0.id AS id_1, t0.iid AS iid_2, t0.lid AS lid_3, t5.fid AS fid_4 FROM pimfields t0 LEFT JOIN BaseValue t5 ON t5.fid = t0.id WHERE t0.iid = ?' with params [1]:SQLSTATE[42S02]: Base table or view not found: 1146 Table 'myproject2.BaseValue' doesn't exist
In the documentation you can read that:
A mapped superclass cannot be an entity, it is not query-able and persistent relationships defined by a mapped superclass must be unidirectional (with an owning side only)
You have an inverse side $value
defined in the Field
entity pointing to the mapped-super-class BaseValue
. This is not allowed and is most likely causing issues.
I suggest reading all documentation on using the doctrine @MappedSuperClass
correctly before continuing, since it is very important to follow the documentation to prevent issues.
It would also be advisable to do some validation of your doctrine model schema during development to make sure that all your mappings are correct.