しろあじ備忘録

システム関係の備忘録。ザルのような記憶力なので、こうして書いておかないと忘れるのだよ。

【CodeIgniter】 is_uniqueで考えた

CodeIgniterのバリデーション、あらかじめいくつかルールが用意されていて、
ぼちぼちとそれで賄っていたが、あるときプチ壁にぶつかった。
is_unique だ。

CodeIgnitervalidation フォームバリデーション

例えばの仕様でざっくりと
「ユーザーメンテ処理で携帯番号が他のユーザーと重複させたくない」
をバリデーションで対応しようと思った。

CodeIgniterマニュアルをざっと見ると、
is_uniqueなるものがある。
このルールの仕様は、

DBにアクセスしてデータがユニーク(一意)であるか確認します。DBは「default」が利用されます

と、なんかよさげ。

is_uniqueてどう?

早速

is_unique[user_tbl.tel] (例)
 などと、パラメータにテーブル名.カラム名を渡してみた。

新規登録時はこれで動作した、
が、変更時だ。Aさんの名前を変更してupdate処理の前にバリデ―ト掛けたら
重複メッセージが出た。
なんてことはない、is_uniqueメソッド内では単純にuser_tblを全検索して telの値をチェックしているのだ。
なので、自分自身(Aさん)レコードを見つけてバリデ―トエラーを返してきてる。

Form_validation.php内のis_uniqueの定義を見れば一目瞭然。

いや、だめだ、そうじゃないんだ。
って、このis_uniqueってどんなときに使うんだ。

仕方ないのでルールを自作する

CI_Form_validationを継承したMY_Form_validation.phpがすでにあったので、
そちらにオリジナルルールを作ることにした。

/local_dir/application/libraries 配下に MY_Form_validation.phpを用意して、

class MY_Form_validation extends CI_Form_validation {
//いろいろ
}

というベタな流れ。

is_uniqueメソッドを参考に新規メソッドを追加する方向で。

is_unique … CI_Form_validation 内の定義を見るとわかるが、

たんにパラメーターで指定しているテーブルに対して、指定した項目のその値があるかどうか、全件検索している。
新規登録時ならいいけど、変更時に自分自身の携帯番号がヒットして「重複エラー」となる。

ユーザーテーブルはIDでAUTO_INCREMENTしているので、
更新時なら、更新対象のID以外に対して検索したい。
あ、「削除日時」を見て、削除済みのユーザーは検索対象から除外したい。

更新対象のIDはPOSTから取得する形にした

is_uniqueをオーバーライドしたよ。
ここに載せる際に微調整したから、このまんまでは動作しないかも(適当でごめんね)

<?php
function is_unique($str,$field){

	sscanf($field, '%[^.].%[^.]', $table, $field);

	$sql = "SELECT * FROM " . $table ." ";
	$sql .= "WHERE " . $field. " = ?  ";
	if (!empty($this->_field_data['id']['postdata'])){ //更新時かどうか
		$sql .= "AND  id != ?  ";
		$val[] = $this->_field_data['id']['postdata'];
	}
	$sql .= "AND  deleted_datetime IS NULL ";
	return isset($this->CI->db)
		? ($this->$CI->db->query($sql,$val))->num_rows() === 0)
		: FALSE;
}
	
?>

更新時には、必ずPOSTの中に更新対象テーブルのIDが入ってくる、という前提。
$this->_field_data['id']['postdata']といった形でほかのPOST値を参照するのは、
Form_validation.php内のmatches()を参考にした。

このテーブル 削除すると deleted_datetime に値を設定する仕様だから、
削除していないレコードを対象としている。