重写FOSUserBundle的默认表单

原文地址http://symfony.com/doc/current/bundles/FOSUserBundle/overriding_forms.html

重写表单类型

FOSUserBundle为新用户注册, 更新用户信息, 修改密码等功能封装了默认的表单. 这些表单能很好的作用在默认的类以及控制器上. 但假如你想在你的User类里面添加更多的属性, 或者想在注册表单里面添加一些选项时, 就得去修改默认的表单.

假设你创建了一个AppBundle\Entity\User的用户类. 在这个类里面, 你必须添加一个name属性跟用户名以及邮箱地址同时保存下来.此时, 当一个用户在你的网站注册时, 他必须填写他们的姓名以及用户名和邮箱, 密码. 下面的代码是添加了$name属性以及验证的例子.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
// src/AppBundle/Entity/User.php

use FOS\UserBundle\Model\User as BaseUser;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;

class User extends BaseUser
{
/**
* @ORM\Id
* @ORM\Column(type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;

/**
* @ORM\Column(type="string", length=255)
*
* @Assert\NotBlank(message="Please enter your name.", groups={"Registration", "Profile"})
* @Assert\Length(
* min=3,
* max=255,
* minMessage="The name is too short.",
* maxMessage="The name is too long.",
* groups={"Registration", "Profile"}
* )
*/
protected $name;

// ...
}

默认情况下, Registration验证组是在一个新用户注册时被使用的. 请确保将你的name属性添加到了命名为Registration的验证组, 除非你在配置文件中修改了这个值.

如果你尝试使用默认的表单进行注册, 你会发现新添加的name属性并不在表单中. 你需要通过创建一个自定义表单类型并且进行配置, 才能使表单正常运作.

第一步是在你的bundle中添加一个新的表单类型. 下面这个类继承自FOSUserBundle的fos_user_registration类型表单, 并且添加了自定义的name字段.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<?php
// src/AppBundle/Form/RegistrationType.php

namespace AppBundle\Form;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;

class RegistrationType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('name');
}

public function getParent()
{
return 'FOS\UserBundle\Form\Type\RegistrationFormType';

// Or for Symfony < 2.8
// return 'fos_user_registration';
}

public function getBlockPrefix()
{
return 'app_user_registration';
}

// For Symfony 2.x
public function getName()
{
return $this->getBlockPrefix();
}
}

如果你不想复用FOSUserBundle提供的默认字段, 则可以忽略getParent方法, 自己添加所有的字段.

你已经创建好了自定义表单类型, 接着就是将它定义为一个服务并且添加相应的tag. tag的name值必须为form.type并且alias值必须与在添加的表单类型中的getName方法返回的字符串相同. alias是要告诉FOSUserBundle使用哪个自定义表单类型的名称.
下面是你的表单服务的配置示例:

1
2
3
4
5
6
# app/config/services.yml
services:
app.form.registration:
class: AppBundle\Form\RegistrationType
tags:
- { name: form.type, alias: app_user_registration }

最后你需要更新你的FOSUserBundle的配置信息, 以便让FOSUserBundle知道要使用哪个表单来替换默认的表单. 下面是替换注册表单的示例配置.

1
2
3
4
5
6
7
8
# app/config/config.yml
fos_user:
# ...
registration:
form:
type: AppBundle\Form\RegistrationType
# if you are using Symfony < 2.8 you should use the type name instead
# type: app_user_registration

注意在配置文件中是如何使用你的表单类型服务配置中tag的alias值来告诉FOSUserBundle使用你的自定义表单的.

如果你需要在处理表单的时候添加一些逻辑, 你可以添加一个监听者挂载到控制器