I'm working on a project made in Symfony 3.1.10.
I have three entities:
MyEntity 1->n MyPivotEntity
MyPivotEntity n->1 MySuperInheritanceEntity
and I have another entity MyInheritanceEntity which inherit from MySuperInheritanceEntity with a single_table inheritance
I made a CollectionType field of MyPivotEntity in MyEntityType form, but when I createForm from the controller I get a memory exceeded message, because the builder do a database request for each MySuperInheritanceEntity. How can I prevent this? In this case I don't need MySuperInheritanceEntity information at all, I just need MyPivotEntity fields
<?php
/**
* MyEntity
*
* @ORM\Table(name="my_entity")
* @ORM\Entity()
*/
class MyEntity {
/**
* @ORM\OneToMany(targetEntity="MyPivotEntity", mappedBy="myEntity", cascade={"persist"})
*/
private $myPivotEntity;
}
/**
* MyPivotEntity
*
* @ORM\Table(name="my_pivot_entity")
* @ORM\Entity()
*/
class MyPivotEntity {
/**
* @ORM\ManyToOne(targetEntity="MyEntity", inversedBy="myPivotEntity", cascade={"persist"})
*/
private $myEntity;
/**
* @ORM\ManyToOne(targetEntity="MySuperInheritanceEntity", inversedBy="myPivotEntity", cascade={"persist"})
*/
private $mySuperInheritanceEntity;
}
/**
* MySuperInheritanceEntity
*
* @ORM\Table(name="my_super_inheritance_entity")
* @ORM\Entity()
* @ORM\InheritanceType("SINGLE_TABLE")
*/
class MySuperInheritanceEntity {
/**
* @ORM\OneToMany(targetEntity="MyPivotEntity", mappedBy="mySuperInheritanceEntity")
*/
private $myPivotEntity;
}
/**
* MyInheritanceEntity
*
* @ORM\Table(name="my_inheritance_entity")
* @ORM\Entity()
*/
class MyInheritanceEntity extends MySuperInheritanceEntity {
}
class MyEntityType extends AbstractType
{
/**
* {@inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('myPivotEntity', CollectionType::class, [
'entry_type' => MyPivotEntityType::class
]);
}
}
class MyPivotEntityType extends AbstractType
{
/**
* {@inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('somField');
}
}
class MyController extends Controller {
/**
* @Post("/myEntity/update")
*/
public function postMyEntityUpdateAction(Request $request, MyEntity $myEntity) {
$form = $this->createForm(MyEntityType::class, $myEntity);
// here error 500 because of too mach memory
// caused by the MyPivotEntityType which runs a request for each entry,
// trying to retrieve all the information about MySuperInheritanceEntity and MyInheritanceEntity
// even if I don't need it at all
// because of the @ORM\InheritanceType("SINGLE_TABLE")
// deleting the inheritance solves the problem, but I need it
$form->handleRequest($request);
if ($form->isValid()) {
$this->getEm()->flush();
return ['success' => true];
}
$errors = (string) $form->getErrors(true, false);
throw new HttpException(400, $errors);
}
}
The documentation says:
There is a general performance consideration with Single Table Inheritance: If the target-entity of a many-to-one or one-to-one association is an STI entity, it is preferable for performance reasons that it be a leaf entity in the inheritance hierarchy, (ie. have no subclasses).
Also keep in mind:
use plural names for OneToMany association propertiy names:
class MyEntity {
/**
* @ORM\OneToMany(targetEntity="MyPivotEntity", mappedBy="myEntity", cascade={"persist"})
*/
private $myPivotEntities;
}
As an alternative way, you may totaly forget about the inheritance and have separate (previously child) entities with all properties and associations replicated.