Symfony2のForm作成->レンダリング->DB連携はとてもよくできています。通常のプレーンなPHPを用いてFormを作ることも可能ですが、Symfony2の機能を使わない手はないです。
http://symfony.com/doc/current/book/forms.html#creating-form-classes
コントローラー内でFormパーツを作成しテンプレートにレンダリングすることができます。createForm()を使って各パーツを設定してゆくだけでした。
しかしコントローラー内でFormを作成するのはあまりおりこうさんではないということになります。というのも他のページで同じFormを使おうとした時にまた同じコードを書かなくてはいけないからです。ですので、Formの作成部分は別のクラスに外部化します。
Typeを作成する
Formを作成する部分は慣習としてTypeを利用します。src/[NAMESPACE]/[BUNDLENAME]Bundle/Form/Type/[TYPENAME]Type.php
といった感じで作成します。エンティティーなどと関連したわかりやすい名前をつけるとよいです。
実際のソースはこんな感じになります。
// src/[NAMESPACE]/[BUNDLENAME]Bundle/Form/Type/[TYPENAME]Type.php namespace [NAMESPACE]\[BUNDLENAME]Bundle\Form\Type; // Typeで共通に読み込む use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\OptionsResolver\OptionsResolverInterface; // 利用するエンティティーを読み込む use [NAMESPACE]\[BUNDLENAME]Bundle\Entity\[ENTITY]; class [TYPENAME]Type extends AbstractType { public function buildForm(FormBuilderInterface $builder, array $options) { $builder ->add('name', 'text') ->add('phone', 'text'); } public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array('data_class' => '[NAMESPACE]\[BUNDLENAME]Bundle\Entity\[ENTITY]')); } public function getName() { return '[TYPENAME]'; } }いくつか解説すると、まずは自分自身のNAMESPACEを指定します。
namespace [NAMESPACE]\[BUNDLENAME]Bundle\Form\Type;
これをやってあげないと動かない。それからTypeを作成する際に共通で読み込むクラスをuseしてあげます。
// Typeで共通に読み込む use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\OptionsResolver\OptionsResolverInterface;これについては深く考えないでこれがデフォルトと思っていればいいです。
クラス名は[TYPENAME]Type.phpというファイルを作成するのでそのファイル名の部分にしておくのが無難です。extendsにはAbstractTypeを指定しておきます。このTypeはAbstractTypeの拡張クラスだということになります。で、
public function buildForm(FormBuilderInterface $builder, array $options) { ......... }これはもう定形として使ってよいです。この$builderにFormのパーツをどんどんaddしてゆくという段取りになります。最終的にはこのクラスをコントローラ内でまるまるcreateForm()に渡してあげればFromが作成されることになります。
さて、もう1つメソッドがあります。setDefaultOptions()は正直何をやっているんだかわかりません。おそらくそのうちわかってくるんだと思いますが、これがないと何だかよくわからないエラーに見舞われました。なのでこれは定形としてつけておくのがよかばいといった感じです。
最後にgetName()メソッドでType名を返してあげる、で終わりです。