2017-03-21 2 views
0

私は実行時にymlからフォームを作成しています。私はymlファイルの要素を調べ、フォームに適切なフィールドを追加します。ルートフォームはYMLが同様の収集フィールドを定義するオプションがあります。このSymfony2:工場ビルダーを使用して作成したフォームを別のフォームのコレクションタイプフィールドに追加するにはどうすればいいですか?

$form = $factory->createBuilder("form", $this->userData); 

のように作成されます。 コレクションフィールドはタイプstringSymfony\Component\Form\ResolvedFormTypeInterfaceである必要があり、供給されるtypeオプション、Symfony\Component\Form\FormTypeInterface

しかし、私は、実行時にも同様に埋め込まれたフォームを構築しておりますので、私は文句を言わないタイプがあり、どちらもここFormTypeInterface

が必要です私はここで

$options = isset($config["options"]) ? $config["options"]: []; 
if ($config['type'] == 'collection') { 
    $options['type'] = $this->buildForm($options['template'], $factory); 
    unset($options['template']); 
    $form->add($config["name"], $config["type"], $options); 
} 

$options['template']を行うために必要なもののサンプルコードが埋め込まれたフォームの種類がYMLファイルに定義されている方法です。そのフォームは実行時にもビルドされます。それをルートフォームにどのように埋め込むのですか?

編集: 実際には、コレクションフィールドにemailという1つのフィールドしかない場合、正常に動作します。しかし、yml仕様では、コレクションフィールド内で複数のフィールドを定義することができます。 symfonyでは、これは組み込みフォームタイプを定義し、コレクションフィールドタイプのtypeオプションをそのフォームタイプに設定することによって行われます。しかし、実行時にフォームを作成するにはどうしたらいいですか?

+0

戦略パターンを実装します。 ymlで定義された型のそれぞれについて、特定のフォーム型をルートフォームに追加する特定のクラスを実装します。これらのクラスは、たぶん1つのメソッドしかないインターフェースを実装します。 'addType()'また、ルートフォームをコンストラクターの引数として受け入れるので、タイプを追加できます。それから私は同じ方法でコレクション型のためにこれを拡張します。 –

+0

これらのymlファイルは何千もあり、実行時にそれらをレンダリングする必要があります。 Theres何千ものクラスを作成するオプションはありません..また、PHPは、実行時にインターフェイスに基づいてクラスを定義することを許可していません! – Broncha

+0

ちょうどアイデアは、多分役立ちます。フォームの種類ごとに1つのクラス(フィールド)を意味します。限られたフォームタイプのセットがあります。テキスト、選択肢、テキストエリア、..それらのそれぞれのクラス。次に、ルートフォームクラスは、イベントサブスクライバを使用し、pre_set_dataイベントに対して、提供されたデータに基づいてこれらのフィールドを追加できます。あなたの場合、ymlから来る文字列のセット。 symfonyのダイナミックフォームを確認してください:http://symfony.com/doc/2.8/form/dynamic_form_modification.html –

答えて

0

実行時にフォームを作成するフォームタイプクラスを定義して解決しました。 config(フォームデザイン)はコンストラクタに渡され、buildFormはデザインに従ってそれぞれのフィールドを追加します。タイプがcollectionタイプがこのフォームタイプを初期化し、ルートフォームに追加され

class RuntimeFormType extends AbstractType 
{ 
    /** 
    * @var string 
    */ 
    private $name; 

    /** 
    * @var array 
    */ 
    private $config; 

    /** 
    * RuntimeFormType constructor. 
    * @param string $name 
    * @param array $config 
    */ 
    public function __construct($name, array $config) 
    { 
     $this->name = $name; 
     $this->config = $config; 
    } 

    public function buildForm(FormBuilderInterface $builder, array $options) 
    { 
     foreach($this->config as $config){ 
      $options = isset($config["options"]) ? $config["options"]: []; 

      if($config['type'] == 'image'){ 
       $options['data_class'] = null; 
       $options['multiple'] = false; 

       $options['attr'] = [ 
        "accept" => "images/*" 
       ]; 

       $builder->add($config["name"], "file", $options); 
      }else{ 
       $builder->add($config["name"], $config["type"], $options); 
      } 
     } 
    } 


    public function getName() 
    { 
     return $this->name; 
    } 
} 

とビルダーで、。

if ($config['type'] == 'collection') { 
    $template = $options['template']; 

    unset($options['template']); 
    $options['type'] = new RuntimeFormType($config["name"], $template); 

    $form->add($themeConfig["name"], $themeConfig["type"], $options); 
} 
関連する問題