74
78

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【CakePHP】バリデーションメソッドをまとめた

Last updated at Posted at 2019-12-07

#はじめに#
CakePHP(3.8)のバリデーションメソッドまとめです。
バリデーションの基本は、Validationクラスのインスタンスに、チェーンメソッドで適応したルールを記述していきます。

use Cake\Validation\Validator;

$validator = new Validator();

$validator
    ->requirePresence('age')
    ->notEmpty('age', 'このフィールドに入力してください')
    ->nonNegativeInteger('age', '年齢は数字で入力してください。')

Validatorクラスは、基本的にはValidationクラスのラッパーになっています。(例外もあります)
そのため、実際にどのような処理が行われるかを知るためには、Validationクラスを覗く必要があります。

Validator.php
public function nonNegativeInteger($field, $message = null, $when = null)
{
    $extra = array_filter(['on' => $when, 'message' => $message]);
    return $this->add($field, 'nonNegativeInteger', $extra + [
        'rule' => ['naturalNumber', true]
    ]);
}

##一覧##

メソッド名 説明
add ルールを追加する
addNested ネストされたデータをバリデートする
addNestedMany 1対多の関係をバリデートする
remove ルールを削除する
requirePresence フィールドに存在することを要求する。nullは許容する
allowEmpty 空を許容する。3.7から非推奨
notEmpty 空を認めない。フィールドに存在することは要求しない。3.7から非推奨
notBlank 空を認めず、更に半角スペースも認めない
allowEmptyString 空を許容し、かつ文字列か
notEmptyString 空を認めず、かつ文字列か
allowEmptyArray 空を許容し、かつ配列か
notEmptyArray 空を認めず、かつ配列
allowEmptyFile 空を許容し、かつファイルか
notEmptyFile 空を認めず、かつファイルか
allowEmptyDate 空を許容し、かつ日付型か
notEmptyDate 空を認めず、かつ日付型か
allowEmptyTime 空を許容し、かつ時刻か
notEmptyTime 空を認めず、かつ時刻か
allowEmptyDateTime 空を許容し、かつdatetime型か
notEmptyDateTime 空を認めず、かつdatetime型か
alphaNumeric 半角英数字か
lengthBetween 指定した文字数の範囲か
creditCard クレジットカードの形式か
greaterThan 指定した数字を超えるか
greaterThanOrEqual 指定した数字以上
lessThan 指定した数字未満
lessThanOrEqual 指定した数字以下
equals 指定した数字と一致
notEquals 指定した数字と不一致
sameAs 指定したフィールドと一致(厳格な比較)
notSameAs 指定したフィールドと不一致(厳格な比較)
equalToField 指定したフィールドと一致
notEqualToField 指定したフィールドと一致
greaterThanToField 指定したフォールドを超える
greaterThanOrEqualToField 指定したフィールド以上
lessThanToField 指定したフィールド未満
lessThanOrEqualToField 指定したフィールド以下
containsNonAlphaNumeric 指定した回数英数字以外が含まれているか
date ymd形式がどうか
datetime datetime形式がどうか
time 時刻の形式かどうか
boolean 真偽値かどうか
decimal 十進数小数か
email メールアドレス形式か
ip IPアドレスの形式か
ip4 IPv4の形式か
ip6 IPv6の形式か
minLength スカラ値が指定した文字数以下か
maxLength スカラ値が指定した文字数以下か
minLengthBytes スカラ値が指定したバイト数以下か
maxLengthBytes スカラ値が指定したバイト数以下か
numeric is_numericか
naturalNumber 自然数かどうか
nonNegativeInteger 0以上の自然数か
range 指定した範囲の数値か
url urlの形式か
urlWithProtocol urlの形式で、スキーマが必須
inList リストの中に存在するか
uuid uuidか
uploadedFile ファイルの形式か
latLong 経度または緯度の形式か
latitude 経度か
longitude 緯度か
ascii ASCII文字か
utf8 BMP UTF-8文字か
utf8Extended UTF-8文字か
integer 数字か
isArray 配列か
isScaler スカラ値か
hexColor 16進数カラーコードか
multipleOptions 複数選択セレクトボックスの値か
hasAtLeast フィールドが指定された数以上の要素をもつか
hasAtMost フィールドが指定された数以下の要素をもつか
regex フィールドが正規表現に一致するか

#共通してる引数#
##$field##
バリデーションの対象となる配列の、バリデーションをかけたいフィールドをキーを渡します。
これは、配列で渡すことによって、複数のフィールドを同時にバリデーションを適応することが可能です。

##$message = null##
バリデーションが発動した際の、エラーメッセージを指定します。この引数が渡されなかった場合、デフォルトのエラーメッセージが出力されます。

##$when = null##
以下の3つから選択することができます。

  • create 新規作成時にバリデーションを適応する
  • update 更新時にバリデーションを適応する
  • コールバック関数

3つ目のコールバック関数について、具体例を提示します。

$validator->requirePresence('credit_card', function ($context) {
    if(isset($context['data']['payment']) {
        $context['data']['payment'] === 'credit';
    }
    return false;
});

コールバック関数の戻り値は、真偽値か、エラーメッセージを意味する文字列である必要があります。
$context['data']には、同時に送られた配列が入っています。
これは、支払い方法がクレジットカードの場合には、クレジットカード番号が必須項目となる例です。

#ルールに関するメソッド#
これらは、他のメソッドと異なり、ルールを追加するために使用されるメソッドです。

##add#

$validtor->add($field, $name, $rule = [])

新しいルールを追加することができます。
以下のように既存のルールを追加することができますが、基本的にはラッパーから読んだほうが簡潔になります。

// これらは同じルールが適応される。addを使用して追加した場合には、ルールの名前を決めることができる。
$validator->add('password', [
    'size' => [
        'rule' => ['lengthBetween', 8, 20],
        'message' => 'パスワードは8文字以上20文字以下にする必要があります。'
    ]
]);

$validator->lengthBetween('password', [8, 20], 'パスワードは8文字以上20文字以下にする必要があります。');

addが真価を発揮するのは、自分で作ったルールを適応させられるところです。

##addNested##

$validator->addNested($field, Validator $validator, $message = null, $when = null)

バリデーションインスタンスを与えて、バリデーションをネストすることができます。
とはいえ、エンティティをバリデーションする際には、アソシエーションするモデル側でバリデーションルールを記述すれば、通常ネストされている
バリデーションも適応されるので、これはモデルのないフォームに利用されます。

##addNestedMany##

$validator->addNestedMany($field, Validator $validator, $message = null, $when = null)

1:多の関係をネストします。addNestedと同じく、モデルのないフォームに利用されます。

##remove##

$validator->remove($field, $rule = null)

フィールドのルールを削除します。$ruleには、ルール名を指定します。
$ruleが指定されなかったときは、そのフィールドのすべてのルールが削除されます。

#通常のバリデーションメソッド#
##requirePresence##

$Validator->requirePresence($field, $mode = true, $message = null)

バリデーションの対象となる配列のフィールドに対して、実在することを求めます。
具体的には、array_key_existsを用いてキーの存在を確かめるため、nullは許容されます。
そのため、notNull制約を実現したい場合には、notEmptyなどと組み合わせて使うことが一般的です。

また、$modeを指定することによって、以下の5つのモードを選択することができます。デフォルトはtrueです。

  • true 常にこのフィールドが存在することが求められる。
  • false フィールドが存在する必要がなくなる。
  • create 新規作成時にバリデーションを適応する
  • update 更新時にバリデーションを適応する
  • コールバック関数

一般的なバリデーションメソッドと引数の順番が違うのは、requirePrecenceはラッパーメソッドではないからです。

##allowEmpty##

$validator->allowEmpty($filed, $when = null, $message = null)

空を許可します。これも、ラッパーメソッドではないので、引数の順序が異なります。
3.7からは、非推奨となり、代わりに以下のメソッドを使うことが推奨されています。

  • notEmptyString()
  • notEmptyArray()
  • notEmptyFile()
  • notEmptyDate()
  • notEmptyDatetime()
  • notEmptyTime()

##notEmpty##

$validator->notEmpty($field, $message = null, $when = null)

空を認めません。具体的には '' や、 null 、 [] といった値(空の配列)です。これもラッパーメソッドではありません。
allowEmptyと同じく、3.7から非推奨となり、以下のメソッドの使用が推奨されています。

  • notEmptyString()
  • notEmptyArray()
  • notEmptyFile()
  • notEmptyDate()
  • notEmptyDatetime()
  • notEmptyTime()

##notBlank##

$validator->notBlank($field, $message = null, $when = null)

空を認めないところはnotEmptyと同じですが、相違点は空白文字も認めないところです。
全角スペースは通してしまうので、注意が必要です。

##alphaNumeric##

$validator->alphaNumeric($field, $message = null, $when = null)

英数字だけであることをチェックします。
内部的にはなんだか見慣れない正規表現が使われています。

Validation.php
public static function alphaNumeric($check)
{
    if (empty($check) && $check !== '0') {
        return false;
    }
    return self::_check($check, '/^[\p{Ll}\p{Lm}\p{Lo}\p{Lt}\p{Lu}\p{Nd}]+$/Du');
}

これは、Unicodeカテゴリでチェックされていることがわかります。

そのため日本語は弾いてくれません:cry:
/^[a-zA-Z0-9]+$/のような正規表現を使いましょう。

##lengthBetween##

$validator->lengthBetween($field, array $range, $message = null, $when = null)

数字の範囲を配列で渡して指定します。

##creditCard##

$validator->creditCard($field, $type = 'all', $message = null, $when = null)

クレジットカードの形式かどうかをチェックします。$typeはallとfastから指定できます。
allは各クレジットカード会社の形式に沿っているかどうかチェックし、fastはすべての形式を一度だけチェックします。つまり、

$cards = [
    'all' => [
        'amex' => '/^3[47]\\d{13}$/',
        'bankcard' => '/^56(10\\d\\d|022[1-5])\\d{10}$/',
        'diners' => '/^(?:3(0[0-5]|[68]\\d)\\d{11})|(?:5[1-5]\\d{14})$/',
        'disc' => '/^(?:6011|650\\d)\\d{12}$/',
        'electron' => '/^(?:417500|4917\\d{2}|4913\\d{2})\\d{10}$/',
        'enroute' => '/^2(?:014|149)\\d{11}$/',
        'jcb' => '/^(3\\d{4}|2131|1800)\\d{11}$/',
        'maestro' => '/^(?:5020|6\\d{3})\\d{12}$/',
        'mc' => '/^(5[1-5]\\d{14})|(2(?:22[1-9]|2[3-9][0-9]|[3-6][0-9]{2}|7[0-1][0-9]|720)\\d{12})$/',
        'solo' => '/^(6334[5-9][0-9]|6767[0-9]{2})\\d{10}(\\d{2,3})?$/',
        'switch' => '/^(?:49(03(0[2-9]|3[5-9])|11(0[1-2]|7[4-9]|8[1-2])|36[0-9]{2})\\d{10}(\\d{2,3})?)|(?:564182\\d{10}(\\d{2,3})?)|(6(3(33[0-4][0-9])|759[0-9]{2})\\d{10}(\\d{2,3})?)$/',
        'visa' => '/^4\\d{12}(\\d{3})?$/',
        'voyager' => '/^8699[0-9]{11}$/'
    ],
    'fast' => '/^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|6011[0-9]{12}|3(?:0[0-5]|[68][0-9])[0-9]{11}|3[47][0-9]{13})$/'
];

こういうことですね。

##greaterThan##

$validator->greaterThan($field, $value, $message = null, $when = null)

$valueで指定した数字を超えることをチェックします。
$field > $value

##greaterThanOrEqual##

$validator->greaterThanOrEqual($field, $value, $message = null, $when = null)

$valueで指定した数字以上であることをチェックします。
$filed >= $value

##lessThan##

$validator->lessThan($field, $value, $message = null, $when = null)

$valueで指定して数字未満であることをチェックします。
$field < $value

##lessThanOrEqual##

$validator->lessThanOrEqual($field, $value, $message = null, $when = null)

$valuedで指定した数字以下であることをチェックします。
$field <= $value

##equals##

$validator->equals($field, $value, $message = null, $when = null)

$valueで指定した数字と一致することをチェックします。緩やかな比較(==)が使われます。
$field == $value

##notEquals##

$validator->notEquals($field, $value, $message = null, $when = null)

$valueで指定した数字と一致しないことをチェックします。緩やかな比較(!=)が使われます。
$field != $value

##sameAs##

$validator->sameAs($field, $secondField, $message = null, $when = null)

バリデーション対象の配列の他のフィールドと一致することをチェックします。厳密な比較(===)が使われています。
$field === $secondField

##notSameAs##

$validator->notSameAs($field, $secondField, $message = null, $when = null)

バリデーション対象の配列の他のフィールドと一致することをチェックします。厳密な比較(!==)が使われています。
$field !== $secondField

##equalToField##

$validator-> equalToField($field, $secondField, $message = null, $when = null)

バリデーション対象の配列の他のフィールドと一致することをチェックします。緩やかな比較(==)が使われています。
$field == $secondField

##notEqualToField##

$validator->notEqualToField($field, $secondField, $message = null, $when = null)

バリデーション対象の配列の他のフィールドと一致することをチェックします。緩やかな比較(!=)が使われています。
$field != $secondField

##greaterThanToField##

$validator->greaterThanToField($field, $secondField, $message = null, $when = null)

バリデーション対象の配列の他のフィールドを超えることをチェックします。
$field > $secondField

##greaterThanOrEqualToField##

$validator->greaterThanOrEqualToField($field, $secondField, $message = null, $when = null)

バリデーション対象の配列の他のフィールド以上であることをチェックします。
$filed >= $secondField

##lessThanToField##

$validator->lessThanToFieldToField($field, $secondField, $message = null, $when = null)

バリデーション対象の配列の他のフィールド未満であることをチェックします。
$field < $secondField

##lessThanOrEqualToField##

$validator->lessThanOrEqualToField($field, $secondField, $message = null, $when = null)

バリデーション対象の配列の他のフィールド以下であることをチェックします。
$field <= $secondField

##containsNonAlphaNumeric##

$validator->containsNonAlphaNumeric($field, $limit = 1, $message = null, $when = null)

英数字が含まれているかどうかをチェックします。$limitを指定すると、その回数だけ英数字が含まれていることを要求します。

alphaNumericとは違う正規表現が使われています。

$matches = preg_match_all('/[^a-zA-Z0-9]/', $check);

##date##

$validator->date($field, $formats = ['ymd'], $message = null, $when = null)

日付の形式かどうかをチェックします。$formatsをymd形式で指定することができます。
指定できる形式は以下のとおりです。

  • dmy 27-12-2006 or 27-12-06
  • mdy 12-27-2006 or 12-27-06
  • ymd 2006-12-27 or 06-12-27
  • dMy 27 December 2006 or 27 Dec 2006
  • Mdy December 27, 2006 or Dec 27, 2006
  • My December 2006 or Dec 2006
  • my 12/2006 or 12/06
  • ym 2006/12 or 06/12
  • y 2006

日付の区切りは- (スペース) / .が使えます。

##datetime##

$validator->dateTime($field, $formats = ['ymd'], $message = null, $when = null)

dateとtimeの両方をチェックします。
形式は、dateメソッドでしていしたものに加えて、ISO8601を指定することでISO8601形式を使用することができます。

##time##

$validator->time($field, $message = null, $when = null)

時刻の形式かチェックします。
具体的には、(HH:MM)か、([H]H:MM[a|p]m)の形式です。

##localizedTime##

$validator->localizedTime($field, $type = 'datetime', $message = null, $when = null)

地域化された日付形式化チェックします。
具体的には\Cake\I18n\Timeのメソッドを使用してチェックされます。
形式は以下の3つから選ぶことができます。

  • datetime \Cake\I18n\Time::parseDateTime()`
  • date \Cake\I18n\Time::parseDate()`
  • time \Cake\I18n\Time::parseDate()`

##boolean##

$validator->boolean($field, $message = null, $when = null)

true, false, 0, 1, '0', '1'に一致するかどうかチェックします。
文字列の0と1も許容します。

##decimal##

$validator->decimal($field, $places = null, $message = null, $when = null)

decimal型、つまり十進数小数であることをチェックします。
`$place'(小数の桁数)を指定できます。

  • null => カンマ.が含まれている必要はない
  • true => 小数部分が0より大きいか、floatdouble型であることが要求される。カンマ.が含まれている必要がある。
  • 1..N => 数字を指定すると、その桁数小数部分が存在することが要求される。

##email##

$validator->email($field, $checkMX = false, $message = null, $when = null)

$checkMXを指定すると、MXレコードを含めてチェックします。

##ip##

$validator->ip($field, $message = null, $when = null)

IPv4または、IPv6の形式がどうかチェックします。

##ipv4##

$validator->ipv6($field, $message = null, $when = null)

##ipv6##

$validator->ipv6($field, $message = null, $when = null)

##minLength##

$validator->minLength($field, $min, $message = null, $when = null)

mb_strlenをしようして、$minで指定した文字数以下かチェックします。
mb_strlen($check) >= $min

##maxLength##

$validator->maxLength($field, $max, $message = null, $when = null)

mb_strlenをしようして、$maxで指定した文字数以上かチェックします。
mb_strlen($check) <= $max

##minLengthBytes##

$validator->minLengthBytes($field, $min, $message = null, $when = null)

strlenをしようして、$minで指定したバイト数以下かチェックします。
strlen($check) >= $min

##maxLengthBytes##

$validator->maxLengthBytes($field, $max, $message = null, $when = null)

strlenをしようして、$maxで指定したバイト数以上かチェックします。
strlen($check) <= $max

##numeric##

$validator->numeric($field, $message = null, $when = null)

is_numericを使用してチェックされているので、
16進数表記0x5391337e0なども認められます。

##naturalNumber##

$validator->naturalNumber($field, $message = null, $when = null)

自然数かどうかを、正規表現を用いてチェックしています。
0は自然数に含みません。

/^[1-9][0-9]*$/

##nonNegativeInteger##

$validator->nonNegativeInteger($field, $message = null, $when = null)

0以上の整数か、つまり0を含む自然数かどうかチェックしています。
実際、参照先はnaturalNumberと同じく\Cake\Validation\Validation::naturalNumber()です。

/^(?:0|[1-9][0-9]*)$/

##range##

$validator->range($field, array $range, $message = null, $when = null)

lengthBetweenと似ていますが、こっちは数字が有効の範囲化チェックします。
$rangeで指定する数字は、float型もOKです。

##url##

$validator->url($field, $message = null, $when = null)

スキーマ、IP、ドメインネーム、パス、クエリー、フラグメントの部分に分けられて判定されます。
スキーマは省略されていても構いません。

##urlWithProtocol##

$validator->url($field, $message = null, $when = null)

前述のurlと同じ参照先ですが、こちらはスキーマの指定が必須になります。
スキーマは以下の通りです。
http(s)/ftp(s)/file/news/gopher

##inList##

$validator->inList($field, array $list, $message = null, $when = null)

フィールドが$listで指定された配列の要素の中にあるか、in_arrayでチェックします。
strvalで文字列に変換してから比較してるので、int型を指定しても特に問題はありません。
(フォームから送られる数字は、通常文字列です。)

$validator->inList('fruit', ['apple', 'banana', 'lemon'])

'apple' => OK
'Kiwi' => NG
'APPLE' => NG

##uuid##

$validator->uuid($field, $message = null, $when = null)

UUIDは、一位となる識別子です。
8桁-4桁-4桁-12桁の16進数で構成されています。

##uploadedFile##

$validator->uploadedFile($field, array $options, $message = null, $when = null)

ファイル形式かどうか調べます。これは、\Psr\Http\Message\UploadedFileInterfaceのインスタンスかどうかで判定しています。
$optionを指定すると、以下の更に以下を指定することができます。

  • types ファイルの拡張子を指定する。
  • minSize ファイルの最小バイト数を指定する。
  • maxSize ファイルの最大バイト数を指定する。
  • optional ファイルがオプションかどうか

##latLong##

$validator->latLong($field, $message = null, $when = null)

##latitude##

$validator->latitude($field, $message = null, $when = null)

##longitude##

$validator->longitude($field, $message = null, $when = null)

##ascii##

$validator->ascii($field, $message = null, $when = null)

##utf8##

$validator->utf8($field, $message = null, $when = null)

##utf8Extended##

$validator->utf8Extended($field, $message = null, $when = null)

##integer##

$validator->integer($field, $message = null, $when = null)

整数かどうかをチェックするので、fload型は受け付けません。
is_intを使ってチェックしていますが、`フォームから来た洗の場合は常に文字列として扱われるため、
そのような場合には正規表現を用いてチェックされています。

Validation.php
if (!($value) || is_float($value)) {
    return false;
}
if (is_int($value)) {
    return true;
}

return (bool)preg_match('/^-?[0-9]+$/', $value);

##isArray##

$validator->isArray($field, $message = null, $when = null)

is_arrayでチェックされています。

##isScaler##

$validator->isScaler($field, $message = null, $when = null)

is_scalerでチェックされています。

##hexColor##

$validator->hexColor($field, $message = null, $when = null)

16進数文字が6回出現するかどうかでチェックしています。

##multipleOptions##

multipleOptions($field, array $options = [], $message = null, $when = null)

複数選択セレクトボックスは、配列で送られてくるので、その形式になっているかチェックします。

$optionsは、以下の選択肢を指定することができます。

  • in => in_arrayで、特定の要素が存在するかチェックします。
  • max => 指定された数を超える数選択されていることをチェックします。
  • min => 指定された数未満選択されていることをチェックします。
  • caseSensitive => tureを指定すると、inでチェックするとき、大文字小文字を無視します。

##hasAtLeast##

$validator->hasAtLeast($field, $count, $message = null, $when = null)

これは、hasManyまたはbelongsToManyにおける特別な配列のキー__idsの数と比較するものです。

hasManyアソシエーションを保存しようとするとき、以下のような_ids形式を使うことができます。

$data = [
    'title' => '私の新しい記事',
    'body' => '本文',
    'user_id' => 1,
    'comments' => [
        '_ids' => [1, 2, 3, 4]
    ]
];

この_idsの数が`$count'で指定したか数未満のとき、バリデーションエラーが発動します。

##hasAtMost##

$validator-> hasAtMost($field, $count, $message = null, $when = null)

フィールドの_ids$count以下かどうかをチェックします。

##regex##

$validator->regex($field, $regex, $message = null, $when = null)

$regexに、正規表現を指定します。

74
78
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
74
78

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?