【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 に値を設定する仕様だから、
削除していないレコードを対象としている。