2012-03-16 115 views
3

我有mysql 2個表:user_profile_fielduser_profile_data與下列:Symfony2的動態形式生成

user_profile_field:

-id (integer) 
-field (string) 
-category(string) 

user_profile_data:

-id (integer) 
-user_id (integer) 
-field_id (integer) references user_profile_field(id) 
-data (string) 

我也定義了2個映射這個關係的Doctrine實體。我需要dynamicaly來創建更新user_profile_data的表單。每行user_profile_field的表單輸入類型取決於user_profile_field:category列(3個可能的值對應於不同的輸入類型:text,textarea和選擇字段)...

我不知道如何創建表單和表單類型實體通過'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; 

然後,您需要基於您收集的user_profile_data創建用戶的數組表示形式。這些數據隨後會綁定到表單上。

我不確定您是否可以直接將此數組版本傳遞給表單。如果表單期望實體,則可能需要先將基本用戶實體傳遞給表單,然後綁定陣列版本(包含動態數據)以設置動態字段值。

這裏,你會使用個人資料表格類:

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); 
     } 

    } 

這個佔地形式的輸出。

在控制器中創建表單。

$profileForm = $this->createForm(new ProfileType($form_config), $user); 

總之,控制方法的結構應是這樣的(填空):

// 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 

我覺得表格活動可能是一個更好的Symfony2的方法,但是這可能會希望幫助你開始了。然後你可以在重構階段考慮表單事件。

+1

你好,非常感謝你的好例子!! ...我會嘗試這種方式...我希望我能把它弄好:)謝謝! – StPiere 2012-03-17 11:39:16

3

symfony的2用戶文檔建議使用形式的事件來生成動態形式:http://symfony.com/doc/current/cookbook/form/dynamic_form_generation.html

+0

這種方法唯一的問題是,由於某種原因(我不知道爲什麼),你必須使用表單工廠而不是表單生成器。這使得添加成員變得更加困難(例如,你失去了猜測類型)。我仍然試圖找到一種使用表單事件的構建器的方法。 – Jens 2012-05-11 07:34:57

+0

我理解表單生成過程中對事件的興趣,但它似乎涉及太多的複雜性,因爲簡單需要繪製某些字段或不是。 – 2012-08-22 09:13:56