[CodeIgniter] フォームからの連想配列データをform_validationライブラリでバリデートする

CodeIgniterでフォームを作る時に便利なのがform_validationライブラリ。ただ、ドキュメントを見ると単純なフォームでの使い方だけで、POSTデータが連想配列になっているケースが想定されていなかったので、やり方をまとめました。

フォームの準備

以下のようなHTMLフォームを例で用意しました。

ブログ本体を格納するblogテーブルと、関連するtagテーブルを一気に追加・更新したいケースをイメージしました。

<form action="/post_confirm/" method="post">
<input type="text" name="blog[id]" value="1">
<input type="text" name="blog[title]" value="タイトル">
<input type="text" name="blog" value="本文">
<input type="text" name="tag[id]" value="10">
<input type="submit" value="確認">
</form>

重要なのは、nameの部分を配列形式にすることで、こうするとPOSTデータは連想配列でPHP(CodeIgniter)に渡されます。

問題と解決の方法

上記の連想配列型のPOSTデータをCodeIgniterのform_validationライブラリでバリデートするのですが、公式ドキュメントの方法は、POSTデータが連想配列のケースを想定していません。

フォームバリデーション(検証) | CodeIgniter ドキュメント

しかし、「form_validation->set_rules」にセットするルールを、POSTのデータの型にマッチした連想配列にしてあげることで、連想配列型のPOSTデータでもCodeIgniterのフォームバリデーションが使えます。

ソースコード

先にソースコードの例を挙げておきます。

ベタコードですが、メソッドにしておくと使いまわしができるのでオススメです。

「エラー文言表示設定」のところは、無くてもOKですが、微妙な英語混じりのエラー文言になるので、面倒でも設定しておくと見やすくなります。

$this->load->helper(array('form', 'url'));
$this->load->library('form_validation');

//バリデートルール
$validate_rule["blog"] = array(
	array(
		"field"=>"id",
		'label' => 'ID',
		'rules' => 'required'
		),
	array(
		"field"=>"title",
		'label' => 'タイトル',
		'rules' => 'required'
		),
	array(
		"field"=>"text",
		'label' => '本文',
		'rules' => 'required'
		),
);

$validate_rule["tag"] = array(
	array(
		"field"=>"id",
		'label' => 'ID',
		'rules' => 'required'
		),
);

$result = "";
$post = $this->input->post();

foreach($post as $key=>$val){
    //エラー文言表示設定
    $this->form_validation->set_message('max_length', '「{field}」の最大文字数は {param} 文字です。');
    $this->form_validation->set_message('min_length', '「{field}」は最低でも{param} の入力が必須です。');
    $this->form_validation->set_message('required', '「{field}」は入力必須です。');
    foreach($validate_rule[$key] as $vrule){
        $this->form_validation->set_rules($key . '[' . $vrule["field"] . "]", $vrule["label"], $vrule["rules"]);                    
    }
    if ($this->form_validation->run() == FALSE){
        $result .= $key . "は" . PHP_EOL;
        $result .= $this->form_validation->error_string();
    }
    //バリデーション結果をリセット
    $this->form_validation->reset_validation();
}

echo $result;

簡単に解説

それでは簡単に解説していきます。

バリデーションルールを連想配列で格納

バリデーションルールは、単純な配列なら公式ドキュメントのように、

$this->form_validation->set_rules(‘username’, ‘ユーザ名’, ‘required’);
$this->form_validation->set_rules(‘password’, ‘パスワード’, ‘required’);
$this->form_validation->set_rules(‘passconf’, ‘パスワード確認’, ‘required’);
$this->form_validation->set_rules(‘email’, ‘メールアドレス’, ‘required’);

とすればOKですが、今回はPOSTデータが連想配列なので、あらかじめ連想配列で$validate_rule変数にルールを格納しておきます。


//バリデートルール
$validate_rule["blog"] = array(
	array(
		"field"=>"id",
		'label' => 'ID',
		'rules' => 'required'
		),
.
.
.

POSTデータをループで回して、専用のバリデーションルールをセットする

続いて、先ほど設定したルールを、実際にform_validation->set_rulesでセットしていきます。

今回のPOSTデータの場合、

form_validation->set_rules(blog[id], "ID", 'required');
form_validation->set_rules(blog[title], "タイトル", 'required');
.
.
.

という形になればいいので、foreachでPOSTデータを回しつつ、$validate_ruleをforeachで回してset_rulesを追加していきます。

foreach($post as $key=>$val){
    foreach($validate_rule as $vrule){
        $this->form_validation->set_rules($key . '[' . $vrule["field"] . "]", $vrule["label"], $vrule["rules"]);                    
    }
.
.
.

バリデーションする

ここまできたらバリデーションができます。エラー文言を表示したい場合は、POSTのキーごとにform_validationのリセットが必要です。

if ($this->form_validation->run() == FALSE){
    $result .= $key . "は" . PHP_EOL;
    $result .= $this->form_validation->error_string();
}
//バリデーション結果をリセット
$this->form_validation->reset_validation();

結果を表示する

エラー文言($this->form_validation->error_string())は、$resultに随時追加されていきますので、ループが終わったところで$resultを表示します。

エラー判定をしたい場合は、$result === “”であれば、バリデートを通過したことになります。

echo $result;
blogは
「ID」は入力必須です。
「タイトル」は入力必須です。
「テキスト」は入力必須です。

tagは
「ID」は入力必須です。

ちゃんとバリデートされていましたね。


もう少しまともな書き方がありそうな気もしますが、取り急ぎ、CodeIgniterでフォームからの連想配列データをform_validationライブラリでバリデートする方法でした。


参考:CodeIgniter validate form with post array values from the database