将EntityManager从Ent​​ityType传递到另一个EntityType

时间:2018-01-02 00:27:02

标签: forms symfony entity options entitymanager

我正在使用Symfony 3.3。

- 摘要:

我有一个表单,我必须在Controller中验证,验证中使用的实体包含一个ArrayCollection属性,这意味着我将使用2个EntityType类(具有CollectionType的父类)验证嵌入的表单孩子一)。

问题是:我想在验证之前通过OptionResolver将EntityManager对象传递给子EntityType以编辑表单数据。

因此,我必须通过2个步骤将EntityManager对象从Controller传递给ChildType:

  • 从Controller到ParentType:已成功完成
  • 从ParentType到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”]

非常感谢您的任何建议。

- Github讨论问题:https://github.com/symfony/symfony/issues/25675

祝你好运

2 个答案:

答案 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');
  }
}

祝你好运