[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
に変換されました。めでたしめでたし。
[Symfony] Doctrine の Repository をサービスコンテナに登録する
AcmeBlogBundle\Repository\BlogRepository
をサービスコンテナに追加:
# @AcmeBlogBundle/Resources/config/services.yml parameters: acme_blog.repository.blog.class: Acme\BlogBundle\Repository\BlogRepository services: acme_blog.repository.blog: class: '%acme_blog.repository.blog.class%' factory_service: doctrine.orm.entity_manager factory_method: getRepository arguments: [ 'AcmeBlogBundle:Blog' ]
要するに $doctrine->getRepository('AcmeBlogBundle:Blog');
の処理をサービスとして定義しているだけです。
// returns true $container->get('acme_blog.repository.blog') === $doctrine->getRepository('AcmeBlogBundle:Blog');
VagrantでNFSを使うときのsudoパスワード入力を省略する方法
Vagrantの共有ディレクトリ設定にNFSを使用している場合、vagrant up
時に毎回sudoのパスワードを入力しないといけません。
なんとかならないものかとググっていたらありました。
Vagrant NFS Shares without a password
どうやら/etc/sudoers
に数行追加するだけのようです。以下のシェルスクリプトを1度だけsudoで実行すれば追加が行えます。
試しにvagrant up
してみたら無事パスワード無しで起動することができました。
[Doctrine] MySQL の TEXT 型を使用する
※Doctrine 2.3 以下でのお話です。
MySQL のカラムにTEXT
型を使おうとして普通に type を text にするとLONGTEXT
型になってしまいます。
/** * @ORM\Column(type="text") */ private $title;
※コンソール結果
$ php app/console doctrine:schema:create --dump-sql > CREATE TABLE ... title LONGTEXT NOT NULL, ...
どうやら length を 65532 にするとTEXT
になるようです。
/** * @ORM\Column(type="text", length=65532) */ private $title;
※コンソール結果
$ php app/console doctrine:schema:create --dump-sql > CREATE TABLE ... title TEXT NOT NULL, ...
因みに 255 でTINYTEXT
, 16777215 でMEDIUMTEXT
, それ以上はLONGTEXT
になるみたいですね。
詳しくは Doctrine/DBAL/Platforms/MySqlPlatform を御覧ください。
追記
※バージョン2.4からはTEXT
の長さが 65535 になるようです。
Doctrine/DBAL/Platforms/MySqlPlatform
[AWS] Root Device が ebs の EC2 から無停止で AMI を生成する
通常 Root Device が ebs の EC2 から AMI イメージを生成する際、インスタンスを一時停止する必要がありますが(自動で停止します)実は無停止で生成する方法も存在するので今回はその手順をご紹介します。
※今回はRightImage_CentOS_6.4_x64_v13.5.0.2_EBS (ami-0f2bbc0e)
から作った EC2 をベースとします。
インスタンス情報の確認
まずは管理コンソールの Instances からインスタンスの情報を確認をします。
Kernel ID と Root Device の値は後で使うので控えておいて下さい。
スナップショットの撮影
次に Volumes を開き、インスタンスのルートデバイスとなっているボリューム(例では sda に接続されている)を選択し、右クリックのメニューから「Create Snapshot」を実行します。
イメージの作成
次に Snapshots を開き、先ほどのスナップショットを確認します。Progress が available (100%) になったら右クリックのメニューから「Create Image from Snapshot」を実行します。
AMI 作成のダイアログが表示されます。
Name は適当に入力して下さい。Architecture は 64bit の CentOS を使用しているのでx86_64
を、
Root Device Name と Kernel ID には先ほど控えた値を入力します。(※ Root Device がsda
の場合は/dev/sda
と入力します。)
続いて画面中部のタブから「Instance Store Volumes」を選択し、Instance Store, Device 共にデフォルト(今回は 0
とsdb
) のまま「Add」 ボタンを押します。
すべて完了したら設定をよく確認し、問題がなければ「Yes, Create」を押します。
(※ Ephemeral Disk を追加していないとインスタンスが正しく起動しないので注意。)
AMI を確認する
AMIs から AMI を確認します。Status が available になっていれば準備完了。
後はここから EC2 を起動するだけです。
尚、今回の作業は全て API Tools からも行えるはずなので自動化も可能です。