CakePHPのモデル内のバリデーションで利用できるバリデーションルールをまとめました。いちいちコメント付けてたらとんでもない時間がかかってしまいましたが、不可解な部分はソースコードを読んで処理を追ったり、サンプルを作って確認したので、cookbookより濃厚なコメントができたと思いますがどうでしょうかね。個人的には色々不明な部分が晴れた気がしたのでスッキリです! なお確認したバージョンは2.4.6です。
モデル内のプロパティとして設定する方法と、後付けで登録する方法(version2.2以降)がありますが、ここではプロパティとして設定する方法を紹介します。
基本形として1つのルールをつける場合は以下のようにします。
2つのルール以上のルールをつける場合は、ルールを配列にします。
このルールを組み合わせてバリデーションを行う事で、少ない手数でバリデーション処理が行えますし、自前で実装しない分、間違いの少ないバリデーションが行えます。
多かったなぁ。
バリデーションの書き方
バリデーションのルールはモデルに書きます。モデル内のプロパティとして設定する方法と、後付けで登録する方法(version2.2以降)がありますが、ここではプロパティとして設定する方法を紹介します。
基本形として1つのルールをつける場合は以下のようにします。
Class Hoge extends AppModel { public $validate = array( 'username'=> 'alphaNumeric', 'email'=> 'email', ); }
2つのルール以上のルールをつける場合は、ルールを配列にします。
Class Hoge extends AppModel { public $validate = array( 'username'=> array( 'alphaNumeric'=> array( 'rule'=> 'alphaNumeric', ), 'minLength'=> array( 'rule'=> array('minLength', 8), ), ), 'email'=> 'email', ); }
バリデーションルールの種類
CakePHPには、デフォルトで多くのバリデーションルールが用意されています。このルールを組み合わせてバリデーションを行う事で、少ない手数でバリデーション処理が行えますし、自前で実装しない分、間違いの少ないバリデーションが行えます。
- alphaNumeric
- データが文字と数字のみである事を検証する。
public $validate = array( 'username'=> array( 'validate1'=> array( 'rule'=> 'alphaNumeric', ), ), );
- between
- データの文字数を設定した最小、最大の間にある事を検証する。
public $validate = array( 'username'=> array( 'validate1'=> array( 'rule'=> array('between', 5, 10), ), ), );
上記の例では5以上10以下の文字数の場合のみTrueを返す。 - blank
- データがスペース、タブ、改行コード、空白のいずれかである事を検証する。Formヘルパーからフォームを作成した時はallowEmptyをtrueにしていないと空白を入力できないので注意。
public $validate = array( 'username'=> array( 'validate1'=> array( 'rule'=> 'blank', 'allowEmpty'=> true, ), ), );
- boolean
- データがtrueかfalseであるか検証する。bool値(true/false)、数字の0/1、文字の"0"/"1"の場合のみTrueを返す。文字列の"true"/"false"は常にFalseを返すのでフォームからTrueを送っても文字列なので検証はうまく通らない。
public $validate = array( 'flg'=> array( 'validate1'=> array( 'rule'=> 'boolean', ), ), );
- cc
- クレジットカードのバリデーション。第2引数は色んなクレジットカードや銀行カードがプリセットされているので、それらを配列でセットするか、全てのカードタイプをチェックする"all"かメジャーなクレジットカードだけをチェックする"fast"が選べる。 また、第3引数でtrueをセットすると、正規表現に加えてLuhnアルゴリズムによるカード番号の妥当性もチェックする。 第4引数に正規表現をセットすると、独自の正規表現でバリデーションする。この場合はカードタイプによる正規表現を無視する。
public $validate = array( 'credit1'=> array( 'validate1'=> array( // allで全てのカードのバリデーションする(Luhnアルゴリズムチェックなし、独自正規表現なし) 'rule'=> array('cc', 'all'), ), ), 'credit2'=> array( 'validate1'=> array( // fastでメジャーなカードのバリデーションする(Luhnアルゴリズムチェックなし、独自正規表現なし) 'rule'=> array('cc', 'fast'), ), ), 'credit3'=> array( 'validate1'=> array( // 引数でバリデーションするカードの種類を選ぶ(Luhnアルゴリズムチェックなし、独自正規表現なし) 'rule'=> array('cc', array('amex', 'visa', 'mc', 'jcb'), ), ), );
- comparison
- 数字の比較検証する。第2引数には、比較する際のオペレーターを設定。第3引数には比較対象の数字をセットする。 オペレーターの種類
- >, isgreater
- より大きい
- <, isless
- より小さい
- >=, greaterorequal
- 以上
- <=, lessorequal
- 以下
- ==, equalto
- 等しい
- !=, notequal
- 等しくない
public $validate = array( 'username'=> array( 'validate1'=> array( // 10以上の場合にTrue 'rule'=> array('comparison', '>=', 10), ), ), );
- custom
- 自作の正規表現でバリデーションする。正規表現をセットされていないとエラーを出す。
文字の比較はできないので別途strcmpなどで比較するカスタムバリデーションを作成する。
public $validate = array( 'username'=> array( 'validate1'=> array( // 先頭がabcで始まっていればTrue 'rule'=> array('custom', '/^abc/'), ), ), );
- date
- データが日付であるか検証する。日付のセパレーターとして利用できるのは、「-」「 (スペース)」「/」「.」の4種類。日付のフォーマットで利用できるのは以下の通り。
- dmy
- 日月年の順で並んでいる数字で表現された日付
- mdy
- 月日年の順で並んでいる数字で表現された日付
- ymd
- 年月日の順で並んでいる数字で表現された日付
- dMy
- 日月年の順で並んでいて、月が英語で表現された日付(英語の月はフルスペル、3文字の略どちらでも良い)
- Mdy
- 月日年の順で並んでいて、月が英語で表現された日付(英語の月はフルスペル、3文字の略どちらでも良い)
- My
- 月年の順で並んでいて、月が英語で表現された日付(英語の月はフルスペル、3文字の略どちらでも良い)
- my
- 月年の順に並んでいる数字で表現された日付
- ym
- 年月の順に並んでいる数字で表現された日付
- y
- 年だけの日付
public $validate = array( 'date'=> array( 'validate1'=> array( // yyyy-mm-ddもしくは、yy-mm-ddのフォーマットで検証する 'rule'=> array('date', 'ymd'), ), ), );
- datetime
- 日付と時間をスペースで連結したデータであるか検証する。日付のチェックに関しては、同じバリデーションルールのdateと同じフォーマットを指定する(というか内部ではdateのルールそのものを使ってバリデーションしている)。
時間は、24時制表記、AM/PMを使った12時制表記、のどちらも利用できる。秒のバリデーションはできない
public $validate = array( 'datetime'=> array( 'validate1'=> array( // yyyy-mm-dd HH:MMもしくは、yy-mm-dd HH:MM AM/PMのフォーマットで検証する 'rule'=> array('datetime', 'ymd'), ), ), );
「00:05」は24時制では深夜0時5分となってTrueとなるが、「00:05 AM」はfalseになる(バグ?)
- decimal
- 実数であるかの検証を行う。正負の符号、有効桁数を表すEが付いていてもチェックできる。
public $validate = array( 'float'=> array( 'validate1'=> array( // 実数チェック 'rule'=> array('decimal'), ), 'validate2'=> array( // 小数点以下の桁数を第2引数に指定 'rule'=> array('decimal', 3), ), ), );
- メールアドレスの検証を行う。
第2引数にtrueをセットすると、MXレコードやDNSなどをチェックしてメールサーバーが存在するかもチェックする(時間かかりそう)。
第3引数に正規表現をチェックするとその正規表現を利用してバリデーションする。
public $validate = array( 'mail'=> array( 'validate1'=> array( // 正規表現による簡単なメールチェック。 'rule'=> array('email'), ), 'validate2'=> array( // 正規表現とネームサーバー問い合わせによるメールチェック。 'rule'=> array('email', true), ), ), );
- equalTo
- データの型、内容を検証する。内部では「===」でチェックしているだけ。strcmpでも実現できるが、strcmpだと、"111"と111は同じと判定される。PHPの型の自動変換の問題。
public $validate = array( 'str'=> array( 'validate1'=> array( // strが文字列の'12345'である事を検証する 'rule'=> array('equalTo', '12345'), ), ), );
- extension
- アップロードしたファイル拡張子をセットした拡張子の配列の中に存在するか検証する。
public $validate = array( 'str'=> ar$validate = array( 'file'=> array( 'validate1'=> array( // ファイルが'mp3', 'mp4', 'aac', 'ogg', 'mov'のいずれかか検証する 'rule'=> array('extension', array('mp3', 'mp4', 'aac', 'ogg', 'mov')), ), ), );ray( 'validate1'=> array( // strが文字列の'12345'である事を検証する 'rule'=> array('equalTo', '12345'), ), ), );
- fileSize
- アップロードしたファイルのファイルサイズを第3引数と比較検証する。第2引数には'<'や'>'などのオペレーターをセットする。セットできるオペレーターの種類はcomparisonバリデーションルールと同じなのでそちらを参照の事。
また第3引数は1MBや500KBなどのように指定できる。
public $validate = array( 'file'=> array( 'validate1'=> array( // ファイルが2MBより大きいか検証する 'rule'=> array('fileSize', 'isgreater', '2MB'), ), ), );
- inList
- データの内容が、第2引数にセットした配列の中に存在するか検証する。
恐らくセレクトボックスやラジオボタンなど、入力値が決まっている場合に利用すると便利でしょうか。
第3引数をtrueにすると型チェックも行う。内部ではin_array関数を通しているだけ。
public $validate = array( 'list'=> array( 'validate1'=> array( // 入力値がonかoffの場合にTrueとなる 'rule'=> array('list', array('on', 'off')), ), ), );
- ip
- データがIPアドレスかどうか検証する。第2引数を省略した場合はv4、v6どちらの検証も行う。
public $validate = array( 'ip'=> array( 'validate1'=> array( // IPアドレスがv4であるか検証する 'rule'=> array('ip', 'IPv4'), // IPV4の指定は大文字小文字どちらでも良い ), ), );
- isUnique
- 入力値がモデルで扱うテーブルの中に存在しないか確認する。
データを検証する際にDB接続してカラムを走査します。
public $validate = array( 'username'=> array( 'validate1'=> array( // usernameがユニークかどうか検証する 'rule'=> array('isUnique'), ), ), );
- luhn
- 入力値をLuhnアルゴリズムで検証する。LuhnアルゴリズムについてはWikipediaを参照のこと。
第2引数を省略するとノーチェックでTrueを返すので、利用する場合は必ず第2引数にtrueをセットする。
public $validate = array( 'luhn'=> array( 'validate1'=> array( 'rule'=> array('luhn', true), ), ), );
- maxLength
- 入力値が指定した文字数以下であることを検証する。どのルールでも言える事だが、maxLengthはmaxlengthでもMAXLENGTHでもいい。
public $validate = array( 'str'=> array( 'validate1'=> array( // 入力値を最大10文字に制限する 'rule'=> array('maxLength', 10), ), ), );
- mimeType
- アップロードしたファイルのMIMEタイプを検証する。第2引数に検証するMIMEタイプを配列でセットする。
内部でfinfo_openとmime_content_typeを使っているが、finfo系の関数はPECL拡張ライブラリなので存在しない可能性もある。その場合はmime_content_typeを代替関数として利用するが、こちらの関数は非推奨なので存在しない可能性もある。両方存在しない場合はたらい回しにされた挙句、Falseとなる。
ちなみにfileinfoのPECL拡張ライブラリを後から追加する方法は過去にmcryptを追加する方法を記事にしてありますが、同じ方法で何とかなります(と思います)。
public $validate = array( 'file'=> array( 'validate1'=> array( 'rule'=> array('mimeType', array('image/jpeg', 'image/gif', 'image/png', 'image/bmp')), ), ), );
- minLength
- 入力値が指定した文字数以上である事を検証する。
public $validate = array( 'str'=> array( 'validate1'=> array( // 文字数が5文字以上ならTrue 'rule'=> array('minLength', 5), ), ), );
- money
- 通貨を示す文字列か検証する。
具体的には通貨記号+数字、もしくは数字+通貨記号、数字のみかのいずれかのパターンであるかを検証する。ちなみに内部ではPHPにプリセットされているpreg_matchの文字プロパティを使ってマッチングしている。
第2引数には通貨記号が数字の右に来るか左に来るかを指定する。日本円¥で検証する場合は'left'をセットする。
public $validate = array( 'jappanesemoney'=> array( 'validate1'=> array( // 通貨記号が左に来る場合は第2引数を省略できる 'rule'=> array('money'), ), ), );
- multiple
- セレクトボックスで複数の入力値を選んだ場合の検証をする。入力した配列の値の個数で最大値、最小値チェック+入力値毎にinListルールの検証をするニュアンスです。
第2引数は配列で、'in'、'min'、'max'をセットします。必須項目はなく、単純に配列内の入力値の個数だけを検証することもできます。
ちなみにcookbookには書いてないですが第3引数にtrue/falseをセットすることもできて、trueの場合は型チェックも行います。デフォルトはtrueです。
public $validate = array( 'select'=> array( 'validate1'=> array( // フォームからの入力値は文字扱いなので、第3引数をfalseにすることで検証できる 'rule'=> array('multiple', array('in'=> array(1, 2, 3, 4, 5, 6), 'min'=> 1, 'max'=> 3), false), ), ), );
- notEmpty
- 入力値が空か検証する。
なかなか使いどころが難しく、他にルールを設定している場合は自動的にnotEmptyの制限がつくのであえてルールを書く必要はない(と思ってます)。空かどうかのチェックだけならもっと簡潔に書ける。
$this->Form->select()の'multiple'=> trueになっているフォームの入力値のバリデーションにこのルールを使うと常にfalseになるので使わない。
public $validate = array( 'string'=> array( 'validate1'=> array( 'rule'=> 'notEmpty', ), ), ); /* * 簡単に書くとこうなる */ public $validate = array( 'string'=> array( 'allowEmpty'=> false, ), );
- numeric
- 入力値が数字であることを検証する。
内部ではis_numericを通しているだけ。
public $validate = array( 'str'=> array( 'validate1'=> array( 'rule'=> 'numeric', ), ), );
- naturalNumber
- 入力値が自然数かどうかの検証をする。0は自然数ではないと学校では教えられますが、第2引数にtrueをセットすることで0も含めることができます。
public $validate = array( 'num'=> array( 'validate1'=> array( // 0を含めた正の整数(自然数)かどうか検証する 'rule'=> array('naturalNumber', true), ), ), );
- phone
- 入力値が電話番号かどうか検証する。第3引数に国を指定して検証できますが、アメリカとカナダしか対応していないようです。従って、日本の電話番号を検証する際は第2引数に正規表現をセットして検証する事になります。
public $validate = array( 'tel'=> array( 'validate1'=> array( // アメリカ国内の電話番号で検証する。 // 日本国内の電話番号に対応した正規表現は電話番号のフォーマットに詳しくない私が書くわけにはいきません:-P 'rule'=> array('phone', null, 'us'), ), ), );
- postal
- 入力値が郵便番号か検証する。こちらもphoneルールと同じく国番号を第3引数にセットすることでその国のフォーマットが選べますが、残念ながら日本は入っていませんでした。
対応しているのは、イギリス(uk)、カナダ(ca)、イタリア(it)、ドイツ(de)、ベルギー(be)、アメリカ(us)です。
public $validate = array( 'zip'=> array( 'validate1'=> array( // 日本の郵便番号用の正規表現で検証する 'rule'=> array('postal', '/^[1-9][0-9]{2}-?[0-9]{4}$/'), ), ), );
- range
- 入力値が指定した範囲内の数字か検証する。入力値が数字ではない場合はfalseになる。
第2引数に最小値、第3引数に最大値をセットする。どちらか、もしくはどちらも省略した場合は、PHP上で有効な有限値であるかをis_finite関数を使ってチェックする。
最大値だけ、最小値だけのチェックはできない模様。
public $validate = array( 'num'=> array( 'validate1'=> array( // 入力値が5より大きく(以上ではない)、100より小さい(以下ではない)か検証する。 'rule'=> array('range', 5, 100), ), ), );
- ssn
- 入力値がソーシャルセキュリティ番号(社会保障番号)かどうか検証する。日本にはこの手の番号はまだ存在していませんのであまり利用する事はないですが、マイナンバー制度が2016年1月から運用されることになった(てか今知った)ので、身分を証明する番号として浸透するでしょう。
public $validate = array( 'str'=> array( 'validate1'=> array( 'rule'=> array('ssn', null, 'us'), ), ), );
- time
- 入力値が時間を表す文字列かどうかを検証する。バリデーションできるのは、24時制の時間:分(HH:MM)もしくは12時制の時間:分(am/pm HH:MM、もしくはHH:MM[A|P]M)のフォーマットで、秒はバリデーションできません。自前の正規表現を通すこともできません。
public $validate = array( 'time'=> array( 'validate1'=> array( 'rule'=> 'time', ), ), );
- uploadError
- ファイルのアップロードが正常にできたか検証する。
public $validate = array( 'file'=> array( 'validate1'=> array( 'rule'=> 'uploadError', ), ), );
- url
- 入力値がURLかどうか検証する。第2引数をtrueにすることで、検証対象のプロトコルをhttp、https、ftp、ftps、sftp、file、news、gopherに制限します。
public $validate = array( 'string'=> array( 'validate1'=> array( // http://example.com/users/edit/1を厳格にチェックする場合 'rule'=> array('url', true), ), ), );
- userDefined
- 入力値を独自のバリデーションクラスを使って検証する。
class myValid { // 文字列'foobar'と比較して同じかどうかをtrue/falseで返す関数 function check($str1){ return !(bool)strcmp($str1, 'foobar'); } } public $validate = array( 'file'=> array( 'validate1'=> array( // myValidクラスのcheck関数を使って検証する。第1引数に入力値が入る 'rule'=> array('userDefined', 'myValid', 'check'), ), ), );
- uuid
- 入力値がuuidであるかどうか検証する。uuidとは重複が(理論上)起こりえない一意な文字列の事。
public $validate = array( 'id'=> array( 'validate1'=> array( 'rule'=> 'uuid', ), ), );
多かったなぁ。
コメント
コメントを投稿