我正在使用Symfony 3.3。
我有一个表单,我必须在Controller中验证,验证中使用的实体包含一个ArrayCollection属性,这意味着我将使用2个EntityType类(具有CollectionType的父类)验证嵌入的表单孩子一)。
问题是:我想在验证之前通过OptionResolver将EntityManager对象传递给子EntityType以编辑表单数据。
因此,我必须通过2个步骤将EntityManager对象从Controller传递给ChildType:
在控制器中:
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 ...
}
在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');
}
}
直到现在,如果我们从上一段代码中删除此行:('em'=> $ options ['em']),则没有错误。
如果我像在ParentType中那样将选项从ParentType传递给ChildType,那么我重新考虑同样的事情,我得到了一个错误(下面)。
让我们完成ChildType类:
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');
}
}
所以在ParentType中,使用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']
);
}
我收到了这个错误:
"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",
甚至在ChildType中定义“em”选项后:configureOptions()方法:
$resolver->setDefaults([
'data_class' => 'Empire\UniversityBundle\Entity\Assignment',
'cascade_validation' => true,
'error_bubbling' => false,
'em' => null,
]);
$resolver->setRequired('em');
我不知道为什么在第一步(将EntityManager从Controller传递给ParentType),它可以工作
但是在第二步(将EntityManager从ParentType传递给ChildType),它不起作用
有关实体的更多详细信息,请在此处找到实体类:
作业:是具有这些属性的子实体
分配:是具有此属性的父实体
-assignments:“分配”实体的ArrayCollection
否则,是否有任何解决方案通过ChildType中的EntityManager?我指的是没有任何黑客的东西,例如使用变量$ options [“label”]或$ options [“attr”]
非常感谢您的任何建议。
祝你好运
答案 0 :(得分:0)
在symfony 3.3 Doc。
中如果您需要从表单类访问服务,请添加正常的__construct()方法:
class AssignmentsType extends AbstractType
{
private $em;
public function __construct(EntityManagerInterface $entityManager)
{
$this->em = $entityManager;
}
...
..
.
如果您正在使用默认的services.yml配置(即已加载Form /的服务并启用了自动配置),这将已经有效!
如果您未使用自动配置,请务必使用form.type标记您的服务。
答案 1 :(得分:0)
我问了一个关于从EntityType向另一个EntityType传递一个对象(不是特别是像EntityManager实例那样具有相同值的服务)的一般性问题:github。
经过一些研究后,我找到了我在此发布的最佳解决方案github answer。
使用相同的行" custom_option"将对象从ParentType传递给ChildType是错误的。在buildForm的第三个参数:ParentType中的add()方法。因为ParentType类包含嵌入表单并将任何选项(甚至是自定义选项)传递给ChildType,所以该选项应该在' entry_options' buildForm的第三个参数的行:add()。否则,该选项将被发送到CollectionType而不是ChildType类。
参考:collection.html#entry-options
因此根据我在第一个问题中的代码(在本主题中),修改后的ParentType应该是这样的:
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');
}
}
祝你好运