備忘録のため,内容の正当性については責任を持ちません。

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" />

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


コメント

コメントする




CAPTCHA