モデルで文字列の長さをvalidateする際にテーブルのカラムサイズを使う方法です。
CakePHPではモデルがテーブルのカラム情報を保持しているのですが、この情報にはカラム名やデータ型の他にカラムサイズ(varchar(N)等)も含まれています。
そこでモデルのvalidateでこの値を使えば最低限テーブルのカラムに収まるかどうかはチェックできます。
ここでは以下のようなテーブルでnameとemailの文字列長をチェックします。(DBはPostgreSQL)
create table users ( id serial primary key ,name varchar(50) not null ,email varchar(100) not null );
1. AppModelにカラムサイズ取得、文字列長チェックメソッドを追加する
AppModelにカラムサイズ取得用メソッド(getColumnLength)と文字列長チェックメソッド(validatesLength)を記述します。
<?php class AppModel extends Model { /** * Returns the column type of a column length in the model * * @param string $column The name of the model column * @return integer * @access public */ function getColumnLength($column) { $columns = $this->loadInfo(); $columns = $columns->value; $cols = array(); foreach($columns as $col) { if ($col['name'] == $column) { return $col['length']; } } return null; } /** * valid value length * * @param array $data * @param string $fields * @access public */ function validatesLength($data, $fields) { foreach ($fields as $v) { $len = $this->getColumnLength($v); if (!empty($data[$v]) && mb_strlen($data[$v]) > $len) { $this->invalidate($v . '_len_' . $len); } } } } ?>
2. モデルで文字列長をチェックする
モデルで文字列長チェックを呼びます。単に$dataとvalidatesLengthメソッドにチェックするカラムを配列で渡すだけでokです。
validatesLength内部ではテーブルのカラムサイズで文字列長チェックを行い、エラーならinvalidateメソッドを呼びます。このinvalidateメソッドに与える値[カラム名 + ‘_len_’ + カラムサイズ]がポイントです。これをモデルの$validationErrorsに持たせておくことにより、ビューで正規の文字列長を含んだエラーメッセージを動的に出力することができます。
<?php function validates($data = array()) { if (!parent::validates($data)) { return false; } if (empty($data)) { $data = $this->data; } $data = $data['User']; // 文字列長チェック $list = array('name', 'email'); $this->validatesLength($data, $list); } ?>
3. HtmlExtヘルパでエラーメッセージを出力
文字列長エラーメッセージを動的に出力するメソッド(tagLengthErrorMsg)をHtmlヘルパーを継承したHtmlExtに定義しておきます。
<?php class HtmlExtHelper extends HtmlHelper { /** * lengthエラーメッセージ表示 * * @param string $field * @param string $name * @return string */ function tagLengthErrorMsg($field, $name) { if (empty($this->validationErrors)) { return null; } $this->setFormTag($field); foreach ($this->validationErrors[$this->model] as $k => $v) { if (preg_match("/^" . $this->field . "_len_([0-9]+)$/", $k, $m)) { $message = sprintf("%sは%d文字以内で入力してください。", $name, $m[1]); return $this->tagErrorMsg($field . "_len_" . $m[1], $message); } } return null; } } ?>
4. ビューテンプレートでヘルパ呼び出し
最後にビューテンプレートで先程のtagLengthErrorMsgメソッドを呼び出します。これは引数としてカラム名とエラーメッセージ用項目名を与えます。
<!-- エラー時は「氏名は50文字以内で入力して下さい。」を表示 --> <?php echo $htmlExt->tagLengthErrorMsg('User/name', '氏名'); ?> <!-- エラー時は「メールアドレスは100文字以内で入力して下さい。」を表示 --> <?php echo $htmlExt->tagLengthErrorMsg('User/email', 'メールアドレス'); ?>
ソース内に文字列長を書かなくて良い
この方法では文字列長をテーブル定義から取得するので、ソースに文字列長を書く必要がありません。もしテーブルのカラムサイズが変わってもソースはそのままで新しいカラムサイズに対応することができます。
(ちなみにtext型などカラムサイズが無いものについてはテーブル定義情報(モデルの$_tableInfo)に直接文字列長を入れるという方法もあります。)
ここでは1.1系で記述していますが、1.2系ではvalidateが柔軟な形になっているので2.のモデルでのチェックはもうちょっとスマートに書けそうです。
- Newer: CakePHP 比較演算子インジェクションに注意
- Older: PHPによる攻撃コードが出現–GIFファイルに隠される?
トラックバック:0
- このエントリーのトラックバックURL
- /blog/2007/06/cakephp_validate_length.html/trackback
- Listed below are links to weblogs that reference
- CakePHP テーブルのカラムサイズでvalidate from Shin x blog