CodeIgniter + Smarty で form_validation に確認画面を設ける

HTML のフォームで「入力画面 → 確認画面 → 完了画面」のような流れを目にする機会は多い。今回は CodeIgniter の form_validation + Smarty でそれを実現する。

確認画面 → 完了画面の間は,session で値を渡すこともできなくはないが,CodeIgniter ではセッションデータを全部クライアントサイド (cookie) に持たせるので hidden と大差ないしちょっと怖い。ということで今回は input の hidden で実装する。

ただし,この方法はファイルを添付するようなフォームには使えない。他にもっとスマートな方法があれば教えてほしい。

コントローラで XSS 対策 (って言えば良いんですか?) をしておけば,Form ヘルパの form_open() 関数または form_hidden() 関数を使って

<?php echo(form_hidden($_POST)); ?>

のようにできなくもないが,それはビューで行ないたいのでこの方法は採用しない。

それではまず,form_validation を継承して自前のライブラリを作る。

$ vi system/application/libraries/MY_Form_validation.php
<?php defined('BASEPATH') or die('No direct script access allowed');

class MY_Form_validation extends CI_Form_validation {

	function __construct($config = array()) {
		parent::__construct($config);
	}

	// フォームから送られた値を連想配列で返す
	function get_values() {
		$result = array();
		foreach ($this->_field_data as $key => $val) {
			if (!is_array($val['postdata']))
				$result[$key] = $val['postdata'];
			else
				$result[$key] = implode("\0", $val['postdata']);
		}
		return $result;
	}

}

get_values() は validation 済みの値を連想配列で返すメソッドである。

そしてコントローラで validation を行ない,成功すれば確認画面を表示する。set_rules() は確認画面も完了画面も同じ内容のはずなので,以下のように,コントローラにそれ用のプライベートメソッドを作っておけば良いだろう。

function _set_validation() {
	$this->form_validation->set_rules(...);
	  :
}

コントローラのメソッドは次のようになる。

function index() {
	$mode = $this->input->post('mode');

	// 確認画面
	if ($mode == 'confirm') {
		$this->_set_validation();
		if ($this->form_validation->run() == true) {
			$this->data['hidden_list'] = $this->form_validation->get_values();
			$this->smarty_parser->parse('ci:<確認画面>.tpl', $this->data);
			return;
		}
	}

	// 送信
	if ($mode == 'submit') {
		$this->_set_validation();
		if ($this->form_validation->run() == true) {
			  :  // 送信処理
			$this->data['hidden_list'] = $this->form_validation->get_values();
			$this->smarty_parser->parse('ci:<完了画面>.tpl', $this->data);
			return;
		}
	}

	// 入力画面
	$this->smarty_parser->parse('ci:<入力画面>.tpl', $this->data);
}

なお,$this->data はテンプレートパーサに値を渡すためのコントローラのメンバ変数 (var $data;) だが,メソッドのローカル変数でも別に構わない。

入力画面のビューは次のようになる。

<form method="post">
	<input type="hidden" name="mode" value="confirm" />
	  :

確認画面のビューでは,入力画面から受け取った値を hidden に挿入する。

<form method="post">
	<input type="hidden" name="mode" value="submit" />
	{foreach from=$hidden_list key="key" item="value"}
	<input type="hidden" name="{$key}" value="{$value|escape}" />
	{/foreach}
	  :

“|escape” は HTML のエスケープを行なう Smarty の修飾子である。

確認画面のビューでユーザの入力値を表示するには,

お名前: {$hidden_list.name|escape}

または

お名前: <?php echo set_value('name'); ?>

のようにすれば良い。

以上で確認画面を作成できた。

ただし,

<input type="text" name="options[]"...

のように配列で渡された場合の動作確認はしていない。

それから,ユーザガイドの フォーム・バリデーション(検証) > フィールド名の指定に配列を使う

フォームの再表示の時はこうです:

<input type="text" name="options[]" value="<?php echo set_value('options[]'); ?>" size="50" />

と書かれているが,これは実際には正常に動作しない。

コメント

タイトルとURLをコピーしました