嵌套表单/映射字段到实体

时间:2017-04-06 08:57:03

标签: php forms symfony

我正在寻找解决以下问题的最佳方法(或仅仅是工作方式)。 我喜欢标准的UserType表单

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder
        ->add(
            'username',
            Type\TextType::class
        )
        ->add(
            'email',
            Type\EmailType::class
        )
        ->add(
            'plainPassword',
            Security\UserRepeatedPasswordType::class
        )
        ->add(
            'roles',
            Type\ChoiceType::class,
            [
                'multiple' => true,
                'expanded' => true,
                'choices' => $this->getRoleChoices()
            ]
        );
}

什么是非标准UserRepeatedPasswordType,它看起来像这样

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder
        ->add(
            'password',
            Type\RepeatedType::class,
            [
                'type' => Type\PasswordType::class,
                'required' => true,
                'first_options'  => [
                    'label' => 'Password'
                ],
                'second_options' => [
                    'label' => 'Repeat Password'
                ],
            ]
        );
}

我创建它是因为这两个字段也用于passwordReset表单和userSettings表单。现在我有两个问题:

1。)当我以这种方式使用它时,来自UserRepeatedPasswordType的值未正确映射到我的User实体 - 有一个错误,即字符串是预期的(duh;)但它有数组。我尝试使用View和Model变换器但没有正确的结果(但我对这些没有太多经验,所以可能就是这种情况)。我还尝试使用getParent()进行试验,然后通过UserType,但它会进入无限循环,我得到500.如果我只是将粘贴字段从UserRepeatedPasswordType复制到UserType它工作正常。

2。)如果这个问题解决了(或者甚至通过复制粘贴,如果不能以其他方式完成),还有另一个相关的(我相信)问题:

我有这个ChangePasswordType表单,用于重置密码。

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder
        ->add(
            'confirmationToken',
            Type\HiddenType::class,
            [
                'required' => true,
                'constraints' => [
                    new NotBlank(),
                ]
            ]
        )
        ->add(
            'plainPassword',
            Type\RepeatedType::class,
            [
                'type' => Type\PasswordType::class,
                'required' => true,
                'first_options'  => [
                    'label' => 'Password'
                ],
                'second_options' => [
                    'label' => 'Repeat Password'
                ],
            ]
        )
        ->add(
            'changePassword',
            Type\SubmitType::class
        );
}

它工作得很好,但我想用它做两件事 - 首先,解决我的第一个问题并在其中使用UserRepeatedPasswordType,第二个 - 我在{{做了一些Assert\Length 1}} User上的实体,当我通过UserType表单提交新用户时,它可以正常工作。但我希望验证有些映射到$plainPassword或理想情况下映射到ChangePasswordType - 只是将所有规则放在一个地方。甚至可以这样做吗?感谢您提供任何解决方案/提示/建议。

1 个答案:

答案 0 :(得分:0)

好的,不知道是否有人有兴趣,但这就是我完成这个的方式。如果有人有更好的答案,请给我一个标志(主要是给第一个);)

1。)正如我所想,由ViewTransformer以父母形式解决(在UserType而非UserRepeatedPasswordType

$builder->get('plainPassword')
    ->addViewTransformer(new CallbackTransformer(
        function ($singleAsArray) {
            return $singleAsArray;
        },
        function ($arrayAsSingle) {
            return $arrayAsSingle['password'] ?? '';
        }
    ));

2。)这实际上非常简单。您所要做的就是以与UserType相同的方式将该表单映射到UserEntity,并制作自定义验证组,以使一切都很好并受到控制:)