Symfony2动态表单生成

StP*_*ere 3 forms dynamic symfony doctrine-orm

我有mysql 2表:user_profile_fielduser_profile_data,包含以下列:

user_profile_field:

-id (integer)
-field (string)
-category(string) 
Run Code Online (Sandbox Code Playgroud)

user_profile_data:

-id (integer)
-user_id (integer)
-field_id (integer) references user_profile_field(id)
-data (string)
Run Code Online (Sandbox Code Playgroud)

我还定义了2个映射此关系的Doctrine实体.我需要dynamicaly来创建一个用于更新user_profile_data的表单.user_profile_field每行的表单输入类型取决于user_profile_field:category列(3个可能的值对应不同的输入类型:text,textarea和choice field)...

我不知道如何通过'Symfony2'方式创建表单和表单类型实体?

任何帮助或建议表示赞赏......

小智 7

我使用的早期解决方案是将定义表单配置的数组传递给表单类型的构造函数方法,并在buildForm方法中构建这些表单字段.

我不知道您是如何设置用户的,因此您需要填写一些空白.

作为一个开始,我认为这将发生在控制器中,但更好的方法是将尽可能多的逻辑移动到像FOS用户包那样的表单处理程序:https: //github.com/FriendsOfSymfony/FOSUserBundle/blob/master/Form /Handler/RegistrationFormHandler.php

您需要获取所有用户配置文件字段并准备好在阵列中准备好添加到表单类型构造函数中(参见ProfileType示例).

$form_config = array(
    'fields' => array()
);

// get all user_profile_field entities add them to $form_config['fields']
// foreach $user_profile_fields as $user_profile_field...
// $form_config['fields'][] = $user_profile_field;
Run Code Online (Sandbox Code Playgroud)

然后,您需要根据您收集的user_profile_data创建用户的数组表示.然后将此数据绑定到表单上.

我不确定你是否可以将这个数组版本直接传递给表单.如果表单需要实体,则可能需要先将基本用户实体传递给表单,然后再绑定数组版本(包含动态数据)以设置动态字段值.

这是您将使用的Profile表单类:

class ProfileType extends AbstractType
{
    // stores the forms configuration
    // preferably map defaults here or in a getDefaultConfig method
    private $formConfig = array();

    // new constructor method to accept a form configuration
    public function __construct($form_config = array())
    {
        // merge the incoming config with the defaults
        // set the merged array to $this->formConfig
        $this->formConfig = $form_config;
    }

    public function buildForm(FormBuilder $builder, array $options)
    {
        // add any compulsory member fields here 
        // $builder->add( ... );

        // iterate over the form fields that were passed to the constructor
        // assuming that fields are an array of user_profile_field entities
        foreach ($this->formConfig['fields'] as $field) {
            // as form is not a straight entity form we need to set this
            // otherwise validation might have problems
            $options = array('property_path' => false);
            // if its a choice fields add some extra settings to the $options

            $builder->add($field->getField(), $field->getCategory(), $options);
        }

    }
Run Code Online (Sandbox Code Playgroud)

这涵盖了表单的输出.

在控制器中创建表单.

$profileForm = $this->createForm(new ProfileType($form_config), $user);
Run Code Online (Sandbox Code Playgroud)

总之,控制器方法的结构应该是这样的(填充空白):

// get the user
// get user data
// create array version of user with its data as a copy

// get profile fields
// add them to the form config
// create form and pass form config to constructor and the user entity to createForm
// bind the array version of user data to form to fill in dynamic field's values


// check if form is valid
// do what is needed to set the posted form data to the user's data
// update user and redirect
Run Code Online (Sandbox Code Playgroud)

我觉得表格事件可能是一个更好的Symfony2方法,但这可能有助于你开始.然后,您可以在重构阶段考虑表单事件.