symfonyのFormで確認画面を実装する方法
こんばんは。
笹亀です。
現在使用している旧MacBook(白)が最近スペックがとてもショボく見えてきましたので、
新しくパソコン(MacBookPro)を新調しました。
インテル製のSSDも入れ変えて快適生活に浸かっています。
さて、今回はsymfonyのFormで確認画面を挟んだシンプルな流れのシステムの作り方です。
いろいろと見てみた感じでちょっとわかりにくい感じでしたので、
最初にsymfonyを始める方のためにもまとめてみたいと思います。
まずは流れについてですが、
確認画面を挟む実装というのは「入力フォーム→確認画面→完了画面」の流れで処理を行うことです。入力画面で情報を入力し、確認画面で入力内容を確認し、完了画面を表示する流れをsymfonyのFormを使って作成していきます。
まずはサンプル用に作成するスキーマ情報は下記のような感じで作成しました。
※モデルの生成などは割愛させていただきます
サンプルにはDoctrineを使用しています
登録フォームのオブジェクトを最低限で編集します。
※ここでは最低限の処理のみの実装です
lib/form/doctrine/MemberForm.class.php
次に入力フォームのアクションを作成します。
※テンプレート側の処理は画像のみとします
apps/user/modules/action/action.class.php
作成して実行すると下記のようなイメージになります。
※jobeetのデザインを使わせてもらいました。

次に確認画面のアクション(confirm)を実装します。
確認画面のアクションを実行されると入力された入力内容がPOSTされますので、
必ず入力内容をFromにbindしないといけません。
apps/user/modules/action/action.class.php
ここで注目すべきは「$this->processForm」です。
「$this->processForm」は確認画面と登録処理実行を分けて行うメソッドとして作成したものです。
実際には下記のように実装します。
apps/user/modules/action/action.class.php
確認画面のテンプレートを用意します。
確認内容の場合はフォームの入力値ではなく、
セットされたモデルのオブジェクトを利用しています。
apps/user/modules/regist/templates/confirmSuccess.php
実際に表示すると。。

登録処理部分の実装します。
※createアクションは表示するテンプレートはありません。
apps/user/modules/action/action.class.php
最後に完了画面のアクションとテンプレートを作って完成です。

長くなってしまいましたが、コツとしてはprocessFormメソッドで処理をまとめることと、
セッションに保存する値はフォームの入力値を保存することです。
※間違えてもセッションにFormオブジェクトは保存しないようにしましょう。
また、processFormをstaticで使用できるようにして汎用的なものにすることで、
同じような「入力フォーム→確認ページ→完了ページ」の流れを
より簡単に作成できるようになります。
---------
※1点修正をさせていただきました
apps/user/modules/regist/templates/confirmSuccess.php
$member_obj = $form->getObject();
sfFormはエスケープ対象にならないので、テンプレート内でFormオブジェクトからgetObjectするとエスケープされず、XSS脆弱性になります。必ずAction側でテンプレート側に渡すようにしましょう。
apps/user/modules/action/action.class.php
$this->member_obj = $this->form->getObject();
詳しい内容については下記をご覧くださいませ。
http://d.hatena.ne.jp/Fivestar/20100608/1275984422
笹亀です。
現在使用している旧MacBook(白)が最近スペックがとてもショボく見えてきましたので、
新しくパソコン(MacBookPro)を新調しました。
インテル製のSSDも入れ変えて快適生活に浸かっています。
さて、今回はsymfonyのFormで確認画面を挟んだシンプルな流れのシステムの作り方です。
いろいろと見てみた感じでちょっとわかりにくい感じでしたので、
最初にsymfonyを始める方のためにもまとめてみたいと思います。
まずは流れについてですが、
確認画面を挟む実装というのは「入力フォーム→確認画面→完了画面」の流れで処理を行うことです。入力画面で情報を入力し、確認画面で入力内容を確認し、完了画面を表示する流れをsymfonyのFormを使って作成していきます。
まずはサンプル用に作成するスキーマ情報は下記のような感じで作成しました。
※モデルの生成などは割愛させていただきます
サンプルにはDoctrineを使用しています
- Member:
actAs: { Timestampable: ~ } tableName: member columns: name: { type: string(255) } email: { type: string(255), notnull: true } login_id: { type: string(255) } password: { type: string(255) }
登録フォームのオブジェクトを最低限で編集します。
※ここでは最低限の処理のみの実装です
lib/form/doctrine/MemberForm.class.php
- /**
* Member form. */ - class
MemberForm extends BaseMemberForm - {
public function configure() { //フォームに使用しないフィールドをunsetする unset( $this['created_at'], $this['updated_at'] ); } - }
次に入力フォームのアクションを作成します。
※テンプレート側の処理は画像のみとします
apps/user/modules/action/action.class.php
- ・
- ・
- ・
public function executeNew(sfWebRequest $request) { //Form生成 $form = new MemberForm(); //確認画面からの戻る処理 if ($request->hasParameter('back')) { //セッションから入力情報を取得 $values = $this->getUser()->getAttribute($form->getName()); //Formにバインドする $form->bind($values, $request->getFiles($form->getName())); //通常新規登録処理 } else { //セッションを初期化する $this->getUser()->setAttribute($form->getName(), null); } $this->form = $form; }
作成して実行すると下記のようなイメージになります。
※jobeetのデザインを使わせてもらいました。
次に確認画面のアクション(confirm)を実装します。
確認画面のアクションを実行されると入力された入力内容がPOSTされますので、
必ず入力内容をFromにbindしないといけません。
apps/user/modules/action/action.class.php
- ・
- ・
- ・
public function executeConfirm(sfWebRequest $request) { //POSTではない場合は404エラーを返す $this->forward404Unless($request->isMethod(sfRequest::POST)); //Formを生成 $form = new MemberForm(); //Formのbind処理 $form = $this->processForm($form, $request); //エラーがある場合は新規登録テンプレート適応 if (!$form->isValid()) { $this->setTemplate('new'); } $this->form = $form; //Action側でForm $this->member_obj = $this->form->getObject(); }
ここで注目すべきは「$this->processForm」です。
「$this->processForm」は確認画面と登録処理実行を分けて行うメソッドとして作成したものです。
- 確認画面の場合:
- 第2引数にsfWebRequestを渡し、
- POSTで送られてきた入力値をFormへbindし、
- 送られてきた値をセッションに保存します。
- 登録処理実行の場合:
- 第2引数にセッションに保存した入力値のデータ配列を渡し、
- Formへbindしてsaveを行います。
実際には下記のように実装します。
apps/user/modules/action/action.class.php
- ・
- ・
- ・
private function processForm(sfForm $form, $request) { //確認画面用のForm処理 if ($request instanceof sfwebRequest) { $values = $request->getParameter($form->getName()); //フォームへバインド $form->bind($values, array()); //Validを通したらオブジェクト更新してセッションに保存 if ($form->isValid()) { $form->updateObject(); sfContext::getInstance()->getUser()->setAttribute($form->getName(), $values); } //登録処理用のForm処理(確認画面からは必ずPUTにする } elseif(sfContext::getInstance()->getRequest()->isMethod(sfRequest::PUT)) { //フォームへバインド $form->bind($request, array()); //Validを通したらオブジェクト更新して登録処理をしてセッションをクリア if ($form->isValid()) { $form->updateObject(); $form->save(); sfContext::getInstance()->getUser()->setAttribute($form->getName(), null); } } return $form; }
確認画面のテンプレートを用意します。
確認内容の場合はフォームの入力値ではなく、
セットされたモデルのオブジェクトを利用しています。
apps/user/modules/regist/templates/confirmSuccess.php
- <?php
use_stylesheets_for_form($form) ?> - <?php
use_javascripts_for_form($form) ?> - <h1>New
member confirm</h1> - <form
action="<?php echo url_for('regist/create') ?>" method="post"> - <input
type="hidden" name="sf_method" value="put" /> - <?php
echo $form->renderHiddenFields() ?> <table> <tfoot> <tr> <td colspan="2"> <input type="button" value="戻る" onClick="location.href='<?php echo url_for('regist/new') . '?back=' ?>'"> <input type="submit" value="登録" /> </td> </tr> </tfoot> <tbody> <tr> <th><label for="member_name"><?php echo $form['name']->renderLabel() ?></label></th> <td><?php echo $member_obj->get('name') ?></td> </tr> <tr> <th><label for="member_email"><?php echo $form['email']->renderLabel() ?></label></th> <td><?php echo $member_obj->get('email') ?></td> </tr> <tr> <th><label for="member_login_id"><?php echo $form['login_id']->renderLabel() ?></label></th> <td><?php echo $member_obj->get('login_id') ?></td> </tr> <tr> <th><label for="member_password"><?php echo $form['password']->renderLabel() ?></label></th> <td><?php echo $member_obj->get('password') ?></td> </tr> </tbody> </table> - </form>
実際に表示すると。。
登録処理部分の実装します。
※createアクションは表示するテンプレートはありません。
- 登録成功:完了画面へリダイレクトする。
- 登録失敗:入力フォームを表示する。
apps/user/modules/action/action.class.php
- ・
- ・
- ・
public function executeCreate(sfWebRequest $request) { //PUTではない場合は404エラーを返す $this->forward404Unless($request->isMethod(sfRequest::PUT)); //Formを生成 $form = new MemberForm(); //bindするパラメータを取得(CSRFも取得) $values = $this->getUser()->getAttribute($form->getName()); //パラメータのチェック $this->forward404Unless($values); //Form処理 $form = $this->processForm($form, $values); //エラーがなく登録が完了していたら完了画面へリダイレクト if ($form->isValid()) { $this->redirect('regist/complete'); } else { $this->form = $form; $this->setTemplate('new'); } }
最後に完了画面のアクションとテンプレートを作って完成です。
長くなってしまいましたが、コツとしてはprocessFormメソッドで処理をまとめることと、
セッションに保存する値はフォームの入力値を保存することです。
※間違えてもセッションにFormオブジェクトは保存しないようにしましょう。
また、processFormをstaticで使用できるようにして汎用的なものにすることで、
同じような「入力フォーム→確認ページ→完了ページ」の流れを
より簡単に作成できるようになります。
---------
※1点修正をさせていただきました
apps/user/modules/regist/templates/confirmSuccess.php
$member_obj = $form->getObject();
sfFormはエスケープ対象にならないので、テンプレート内でFormオブジェクトからgetObjectするとエスケープされず、XSS脆弱性になります。必ずAction側でテンプレート側に渡すようにしましょう。
apps/user/modules/action/action.class.php
$this->member_obj = $this->form->getObject();
詳しい内容については下記をご覧くださいませ。
http://d.hatena.ne.jp/Fivestar/20100608/1275984422
トラックバックURI
最近の記事
システム開発エンジニア募集! [2012年02月03日 : 小林有佳]
OpenVPNで細々便利な設定 [2012年01月31日 : 門脇優児]
【iOS】Viewの開発・デバッグに役立つ色々 [2012年01月23日 : 中川善樹]
PHPDocumentorの利用方法まとめ [2012年01月19日 : 笹亀弘]
Google Chart Toolsを使ってサイトマップを描こう! [2011年12月21日 : 志田仁美]
stumpwm設定v2 [2011年12月19日 : 門脇優児]
Mashup Awards 7の授賞式が行われました [2011年12月16日 : 中川善樹]
社員旅行に行きました [2011年12月12日 : 大橋寛子]
iCloud風のアイコンを作成する(Fireworks) [2011年12月07日 : 和田記光]
iScroll4でネイティブに近いスマホ向けHTMLページを作成する [2011年12月02日 : 松田惇]













コメントフォーム