I'm using Symfony 3.3.
I have a form which I have to validate in the Controller, the entity used in the validation contains an ArrayCollection attribute, which means that I'm going to validate an embeded forms using 2 EntityType classes (a parent one having a CollectionType of child one).
The problem is: I want to pass an EntityManager object to the child EntityType to edit the form data, before the validation, through the OptionResolver.
So, I have to pass the EntityManager Object from the Controller to the ChildType by 2 steps:
From the Controller to the ParentType : successfully done
From the ParentType to the ChildType : I got an error (see below)
Detail:
In the Controller:
public function postAssignmentAction(Request $request)
{
$result = new Assignments();
$em = $this->get('doctrine.orm.entity_manager');
$form = $this->createForm(AssignmentsType::class, $result, array(
'validation_groups' => array('Creation', 'Default'),
'em' => $em,
));
$form->submit($request->request->all()["assignments"]);
//validation ...
}
In the ParentType (AssignmentsType):
class AssignmentsType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
//dump($options['em']); //this line works fine and it dump the EntityManager
$builder->add('assignments', CollectionType::class,array(
'entry_type' => AssignmentType::class,
'required'=> true,
'allow_add' => true,
'by_reference' => false,
'em' => $options['em'] //without this line, there is no error if we delete the ChildType (AssignmentType)
);
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => 'Empire\UniversityBundle\Entity\Assignments',
'cascade_validation' => true,
'error_bubbling' => false,
'em' => null,
]);
$resolver->setRequired('em');
}
}
Until now there is no error if we delete this line : ('em' => $options['em']) from the previous code.
If I reapeat the same thing while passing the options from the ParentType to the ChildType as we did in the ParentType, I got an error (below).
Let's finish with the ChildType class:
class AssignmentType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
dump($options['em']); //this line can't be executed because of the error
$this->em = $options['em'];
$builder->add('full_name');
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => 'Empire\UniversityBundle\Entity\Assignment',
'validation_groups' => array('Creation', 'Default'),
'cascade_validation' => true,
'error_bubbling' => false,
'em' => null,
]);
$resolver->setRequired('em');
}
}
So in the ParentType, using the options of the ParentType:buildForm():
public function buildForm(FormBuilderInterface $builder, array $options){
$builder->add('assignments', CollectionType::class,array(
'entry_type' => AssignmentType::class,
'required'=> true,
'allow_add' => true,
'by_reference' => false,
'em' => $options['em']
);
}
I got this error:
"message": "The option \"em\" does not exist. Defined options are: \"action\", \"allow_add\", \"allow_delete\", \"allow_extra_fields\", \"attr\", \"auto_initialize\", \"block_name\", \"by_reference\", \"compound\", \"constraints\", \"csrf_field_name\", \"csrf_message\", \"csrf_protection\", \"csrf_token_id\", \"csrf_token_manager\", \"data\", \"data_class\", \"delete_empty\", \"disabled\", \"empty_data\", \"entry_options\", \"entry_type\", \"error_bubbling\", \"error_mapping\", \"extra_fields_message\", \"horizontal_input_wrapper_class\", \"horizontal_label_class\", \"horizontal_label_offset_class\", \"inherit_data\", \"invalid_message\", \"invalid_message_parameters\", \"label\", \"label_attr\", \"label_format\", \"label_render\", \"mapped\", \"method\", \"post_max_size_message\", \"property_path\", \"prototype\", \"prototype_data\", \"prototype_name\", \"required\", \"sonata_admin\", \"sonata_field_description\", \"sonata_help\", \"translation_domain\", \"trim\", \"upload_max_size_message\", \"validation_groups\".",
"class": "Symfony\\Component\\OptionsResolver\\Exception\\UndefinedOptionsException",
Even after defining the "em" option in the ChildType:configureOptions() method:
$resolver->setDefaults([
'data_class' => 'Empire\UniversityBundle\Entity\Assignment',
'cascade_validation' => true,
'error_bubbling' => false,
'em' => null,
]);
$resolver->setRequired('em');
I don't know why in the first step (passing the EntityManager from the Controller to the ParentType), it works
But in the second step (passing the EntityManager from the ParentType to the ChildType), it doesn't work
For more details about the entities, you can find here the Entity classes:
Assignment : is the Child Entity which have these attributes
name
description
Assignments : is the Parent Entity which have this attribute
-assignments : an ArrayCollection of "Assignment" entities
Otherwise, is there any solution to pass have the EntityManager in the ChildType ? I mean something without any hack such as using the variable $options["label"] or $options["attr"]
Thank you very much for any suggestion.
I asked a general question about passing an object (not specifically a service like an instance of EntityManager which have the same value wherever) from an EntityType to another EntityType : github.
After some researches I found the best solution that I posted here github answer.
It was a mistake for me to pass an object from a ParentType to a ChildType using the same row "custom_option" in the third parameter of buildForm:add() method in the ParentType. Because the ParentType class contains an embeded form and to pass any option (even a custom one) to the ChildType, the option should be in the 'entry_options' row of the third argument of the buildForm:add(). Otherwise the option will be sent to the CollectionType and not ChildType class.
Reference: collection.html#entry-options
So the modified ParentType should be like this according to my code in my first question (in this subject):
class AssignmentsType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
//dump($options['em']); //this line works fine and it dump the object from the em option
$builder->add('assignments', CollectionType::class,array(
'entry_type' => AssignmentType::class,
'required'=> true,
'allow_add' => true,
'by_reference' => false,
'entry_options' => array('em' => $options['em']) ,// ->>>we modified this line <<<-
);
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => 'Empire\UniversityBundle\Entity\Assignments',
'cascade_validation' => true,
'error_bubbling' => false,
'em' => null,
]);
$resolver->setRequired('em');
}
}
Best regards