问题
Here is the situation:
I have an entity Property
class Property
{
/**
* @ORM\Id
* @ORM\Column(type="string")
* @ORM\GeneratedValue(strategy="UUID")
*/
protected $id;
/**
* @ORM\ManyToMany(targetEntity="PropertyEquipment", inversedBy="properties")
*/
protected $propertyEquipments;
public function __construct()
{
$this->propertyEquipments = new ArrayCollection();
}
public function getId()
{
return $this->id;
}
public function addPropertyEquipment(\AppBundle\Entity\PropertyEquipment $propertyEquipment)
{
$this->propertyEquipments[] = $propertyEquipment;
return $this;
}
public function removePropertyEquipment(\AppBundle\Entity\PropertyEquipment $propertyEquipment)
{
$this->propertyEquipments->removeElement($propertyEquipment);
}
public function getPropertyEquipments()
{
return $this->propertyEquipments;
}
}
And the entity PropertyEquipment:
class PropertyEquipment
{
/**
* @ORM\Id
* @ORM\Column(type="string")
* @ORM\GeneratedValue(strategy="UUID")
*/
protected $id;
/**
* @ORM\ManyToMany(targetEntity="Property", mappedBy="propertyEquipments")
*/
protected $properties;
/**
* @ORM\Column(type="string", length=100)
* @Gedmo\Translatable
*/
protected $equipmentName;
public function __construct()
{
$this->properties = new ArrayCollection();
}
/**
* Get id
*
* @return string
*/
public function getId()
{
return $this->id;
}
/**
* @return mixed
*/
public function getEquipmentName()
{
return $this->equipmentName;
}
/**
* @param mixed $equipmentName
*/
public function setEquipmentName($equipmentName)
{
$this->equipmentName = $equipmentName;
}
public function addProperty(Property $property)
{
$this->properties[] = $property;
return $this;
}
public function removeProperty(Property $property)
{
$this->properties->removeElement($property);
}
public function getProperties()
{
return $this->properties;
}
}
The form PropertyCreation
class PropertyCreation extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
//with this I see the values coming from DB in the template
->add("propertyEquipments", PropertyEquipmentCreation::class)
//with this it's empty :/
/*->add("propertyEquipments", CollectionType::class, array(
"entry_type" => PropertyEquipmentCreation::class,
))*/
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => Property::class
));
}
}
Here is the form PropertyEquipmentCreation:
class PropertyEquipmentCreation extends AbstractType
{
/**
* @param FormBuilderInterface $builder
* @param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('propertyEquipment', EntityType::class, [
'class' => 'AppBundle\Entity\PropertyEquipment',
'choice_label' => 'equipmentName',
'expanded' => true,
'multiple' => true
]);
}
/**
* @param OptionsResolver $resolver
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => PropertyEquipment::class,
]);
}
}
And the controller
public function createPropertyAction(Request $request)
{
$property = new Property();
$form = $this->createForm(PropertyCreation::class, $property);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$entityManager = $this->getDoctrine()->getManager();
$entityManager->persist($property);
$entityManager->flush();
return $this->redirectToRoute('homepage');
}
return $this->render('form/owner_create_property.html.twig', ["form" => $form->createView()]);
}
My error:
Expected value of type "Doctrine\Common\Collections\Collection|array" for association field "AppBundle\Entity\Property#$propertyEquipments", got "Doctrine\Common\Collections\ArrayCollection" instead.
Must I transform these with something like class PropertyEquipmentTransformer implements DataTransformerInterface
?
回答1:
I think you should use getParent()
function in PropertyEquipmentCreation
and inherit from EntityType::class
then put all your field configs in the configureOptions()
function (remove the buildForm
function) and it should work.
You are having this problem because it is a compound form
in your implementation and no simple form
and symfony is unable to resolve which field created inside the subform needs to be used as source for the entity field
回答2:
First !
Big thanks to Nickolaus !
Here is the solution (PropertyEquipmentCreation):
namespace AppBundle\Form\Type;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\OptionsResolver\OptionsResolver;
class PropertyEquipmentCreation extends AbstractType
{
/**
* @param OptionsResolver $resolver
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'class' => 'AppBundle\Entity\PropertyEquipment',
'choice_label' => 'equipmentName',
'expanded' => true,
'multiple' => true,
]);
}
public function getParent()
{
return EntityType::class;
}
}
And for (PropertyCreation)
<?php
namespace AppBundle\Form;
use AppBundle\Form\Type\PropertyEquipmentCreation;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class PropertyCreation extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('description', TextareaType::class)
->add('name', TextType::class)
->add("propertyEquipments", PropertyEquipmentCreation::class)
->add('save', SubmitType::class);
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => Property::class
));
}
}
Many thanks !
回答3:
Try using Doctrine ArrayCollection instead of ArrayCollections:
$this->propertyEquipments = new \Doctrine\Common\Collections\ArrayCollection();
This should work!
来源:https://stackoverflow.com/questions/39751434/symfony-form-many-to-many-relation-collection-type