[Symfony][Form] フィールドタイプはよく考えて決めよう
Symfony2を使い始めて2年くらい経ちましたが、未だ全容をつかみきれない機能の1つがForm。今回はそんなFormのフィールドタイプについて話します。
通常、Symfony2のFormではフィールドタイプを次のようにして定義します。
$builder->add('addressLine', 'text', ['label' => '住所']); $builder->add('latitude', 'hidden'); $builder->add('longitude', 'hidden');
テンプレートはこんな感じ。
{{ form_start(form) }} {{ form_row(form.addressLine) }} <button type="submit">送信</button> {{ form_end(form) }} {# hiddenフィールドはここで自動出力されます #}
この場合、画面上には「住所」を入力するテキストフィールドだけが表示されますが、サブミットの直前に住所の内容からJavaScriptでGoogleMap APIから取得し、hidden
タイプの緯度・経度に位置情報が入る仕様だとします。(実装例は割愛)
サブミットを行うと、データは次のようにマップされます。
$form->handleRequest($request); var_dump($form->getData()); /* * ※DTOは使わないのでデータは配列です。 * [ * 'addressLine' => string '東京都渋谷区...', * 'longitude' => string '35.658534', * 'latitude' => string '139.701330', * ] */
緯度経度がfloat
ではなくstring
となっています。当然といえば当然なのですが...。
因みにはじめからnumber
タイプを定義していれば、適切にfloat
型としてマップされます。
$builder->add('latitude', 'number'); $builder->add('longitude', 'number');
※但しこの場合はinput[type=text]
として画面上にUIが表示されます。
クライアントサイドの都合で安直にhidden
を使うと今回のような悲劇を生みます。(´・ω・`)
解決法は色々ありますが今回のケースではオーソドックスに
DataTransformer
を使うのが良さそうです。
$builder->add( $builder ->create('latitude', 'hidden') ->addViewTransformer(new NumberToLocalizedStringTransformer()) ); $builder->add( $builder ->create('longitude', 'hidden') ->addViewTransformer(new NumberToLocalizedStringTransformer()) );
この他にDataTransformer
を使わずにnumber
タイプを定義しておいて、テンプレート側でhidden
にすると言う方法もあります。
{{ form_start(form) }} {{ form_row(form.addressLine) }} {{ form_row(form.longitude, {type: 'hidden'}) }} {{ form_row(form.latitude, {type: 'hidden'}) }} <button type="submit">送信</button> {{ form_end(form) }}
この場合form_end
でのhidden
フィールド自動出力の恩恵が受けられませんが、最終的なUIがテキストボックスであればこちらの方が良いかもしれません。
Symfony2が予め用意しているフィールドタイプは、number
のようにデータを適切に変換してくれる物が多いからです。
何はともあれこれでデータは適切にfloat
に変換されました。めでたしめでたし。