CakePHP 2.x CookBook 中文版 第七章 模型 之 數據校驗(二)

 

內核覈驗規則

class Validation

CakePHP 的 Validation 類包含許多能使模型數據校驗更容易的校驗規則。這個類包含許多常用的不需要自己編寫的校驗技術。 下面是全部規則的完整列表及其用法示例。

static Validation::alphaNumeric(mixed $check)

列數據必須只包含字母和數字。

public $validate = array(
    'login' => array(
        'rule'    => 'alphaNumeric',
        'message' => 'Usernames must only contain letters and numbers.'
    )
);
static Validation::between(string $checkinteger $mininteger $max)

列的數據長度必須位於指定的數值範圍。必須同時提供最小值和最大值。Uses = not.:

public $validate = array(
    'password' => array(
        'rule'    => array('between', 5, 15),
        'message' => 'Passwords must be between 5 and 15 characters long.'
    )
);

數據的長度是指”字符串數據的字節數”。要小心,當處理非 ASCII 字符時,其值可能大於字符數。

static Validation::blank(mixed $check)

這條規則用於確保列值爲空或者其值僅包含空白字符。空白字符包括 空格、tab、回車和換行。

public $validate = array(
    'id' => array(
        'rule' => 'blank',
        'on'   => 'create'
    )
);
static Validation::boolean(string $check)

列數據必須是邏輯值。有效值包括 true 或 false,整數值 0 或 1,字符串值 ‘0’ 或 ‘1’。

public $validate = array(
    'myCheckbox' => array(
        'rule'    => array('boolean'),
        'message' => 'Incorrect value for myCheckbox'
    )
);
static Validation::cc(mixed $checkmixed $type = 'fast'boolean $deep = falsestring $regex = null)

這條規則用於檢查數據是否是有效的信用卡編號。它有三個參數:‘type’、 ‘deep’ 和 ‘regex’。

‘type’鍵能賦的值有‘fast’、 ‘all’下列值之一:

  • amex
  • bankcard
  • diners
  • disc
  • electron
  • enroute
  • jcb
  • maestro
  • mc
  • solo
  • switch
  • visa
  • voyager

如果‘type’設爲‘fast’,檢驗的是主信用卡的編碼格式。‘type’設置爲‘all’校驗所有信用卡類型。也可以將 ‘type’設置爲希望檢驗的類型的數組。

‘deep’鍵需要設置爲邏輯值。如果爲 true,校驗規則將檢查信用卡的 Luhn 算法(http://en.wikipedia.org/wiki/Luhn_algorithm)。默認值爲 false。

‘regex’鍵允許提供自定義的用於校驗信用卡編號的正則表達式:

public $validate = array(
    'ccnumber' => array(
        'rule'    => array('cc', array('visa', 'maestro'), false, null),
        'message' => 'The credit card number you supplied was invalid.'
    )
);
static Validation::comparison(mixed $check1string $operator = nullinteger $check2 = null)

Comparison 用於比較數字值。支持 “is greater”、”isless”、”greater or equal”、”less or equal”、”equal to” 和 “not equal”。以下爲示例:

public $validate = array(
    'age' => array(
        'rule'    => array('comparison', '>=', 18),
        'message' => 'Must be at least 18 years old to qualify.'
    )
);

public $validate = array(
    'age' => array(
        'rule'    => array('comparison', 'greater or equal', 18),
        'message' => 'Must be at least 18 years old to qualify.'
    )
);
static Validation::custom(mixed $checkstring $regex = null)

用於自定義正則表達式:

public $validate = array(
    'infinite' => array(
        'rule'    => array('custom', '\u221E'),
        'message' => 'Please enter an infinite number.'
    )
);
static Validation::date(string $checkmixed $format = 'ymd'string $regex = null)

這條規則確保提交的數據是正確的日期格式。可以傳遞一個指定要校驗的日期的格式的參數(可以是數組)。此參數可以爲下列之一:

  • ‘dmy’ 例如 27-12-2006 或 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 (間隔符可以是空格、句點、破折號、斜槓)

如果沒有提供這個鍵,就默認使用 ‘ymd’:

public $validate = array(
    'born' => array(
        'rule'       => array('date', 'ymd'),
        'message'    => 'Enter a valid date in YY-MM-DD format.',
        'allowEmpty' => true
    )
);

當許多數據需要用一個特定的格式存儲時,你可能會考慮接受較寬泛的格式並轉換,而不是強制用戶提供一個指定的格式。你可以爲客戶做的更多、更好!

static Validation::datetime(array $checkmixed $dateFormat = 'ymd'string $regex = null)

這條規則確保數據是有效的日期時間格式。可以傳遞一個指定要校驗的日期的格式的參數(可以是數組)。此參數可以爲下列之一:

  • ‘dmy’ 例如 27-12-2006 或 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 (間隔符可以是空格、句點、破折號、斜槓)

如果沒有提供這個鍵,就默認使用 ‘ymd’:

public $validate = array(
    'birthday' => array(
        'rule'    => array('datetime', 'dmy'),
        'message' => 'Please enter a valid date and time.'
    )
);

可以通過傳遞第二個參數來指定自定義正則表達式。如果使用此參數,就以此爲標準進行驗證。

與 date() 不同,datetime() 校驗日期和時間。

static Validation::decimal(integer $checkinteger $places = nullstring $regex = null)

這條規則確保數據是有效的數字。可以傳遞一個指定小數點後的數字位數的參數。如果沒有傳遞參數,數據必須是嚴格意義上的浮點數,如果沒有在小數點後發現數字,校驗就會失敗:

public $validate = array(
    'price' => array(
        'rule' => array('decimal', 2)
    )
);
static Validation::email(string $checkboolean $deep = falsestring $regex = null)

這條規則校驗數據是否爲有效的郵件地址。傳遞一個邏輯值作爲其第二個參數,這條規則將試圖檢查地址中的主機是否是有效的:

public $validate = array('email' => array('rule' => 'email'));

public $validate = array(
    'email' => array(
        'rule'    => array('email', true),
        'message' => 'Please supply a valid email address.'
    )
);
static Validation::equalTo(mixed $checkmixed $compareTo)

這條規則確保數據與給定的值類型相同、數值相等。

public $validate = array(
    'food' => array(
        'rule'    => array('equalTo', 'cake'),
        'message' => 'This value must be the string cake'
    )
);
static Validation::extension(mixed $checkarray $extensions = array('gif''jpeg''png''jpg'))

這條規則校驗文件擴展名是不是 .jpg 或者 .png。允許以數組方式傳遞多個擴展名。

public $validate = array(
    'p_w_picpath' => array(
        'rule'    => array('extension', array('gif', 'jpeg', 'png', 'jpg')),
        'message' => 'Please supply a valid p_w_picpath.'
    )
);
static Validation::fileSize($check$operator = null$size = null)

這條規則允許檢測文件長度。可以使用 $operator 來決定所需的比較類型。所有 comparison() 支持的操作這裏也支持。 此方法將通過讀取 tmp_name 鍵(如果 $check 是一個包含該鍵的數組)自動處理來自 $_FILES 的數組值:

public $validate = array(
    'p_w_picpath' => array(
        'rule' => array('filesize', '<=', '1MB'),
        'message' => 'Image must be less than 1MB'
    )
);

2.3 新版功能: 此方法是 2.3 版增加的。

static Validation::inList(string $checkarray $list)

這條規則確保值在給定的集合中。它需要一個值數組。如果列值與給定的數組中的某個值匹配,則列被視爲有效。

例如:

public $validate = array(
    'function' => array(
         'allowedChoice' => array(
             'rule'    => array('inList', array('Foo', 'Bar')),
             'message' => 'Enter either Foo or Bar.'
         )
     )
 );
static Validation::ip(string $checkstring $type = 'both')

這條規則確保被提交的是有效的 IPv4 或 IPv6 地址。接受參數 ‘both’ (默認值)、’IPv4’ 或者 ‘IPv6’。

public $validate = array(
    'clientip' => array(
        'rule'    => array('ip', 'IPv4'), // or 'IPv6' or 'both' (default)
        'message' => 'Please supply a valid IP address.'
    )
);
static Validation::isUnique

列數據必須唯一,不能是被其它行用過的。

public $validate = array(
    'login' => array(
        'rule'    => 'isUnique',
        'message' => 'This username has already been taken.'
    )
);
static Validation::luhn(string|array $checkboolean $deep = false)

Luhn 算法:各種標識碼的校驗算法。更多信息參見 http://en.wikipedia.org/wiki/Luhn_algorithm 。

static Validation::maxLength(string $checkinteger $max)

這條規則確保數據在最大長度範圍內。

public $validate = array(
    'login' => array(
        'rule'    => array('maxLength', 15),
        'message' => 'Usernames must be no larger than 15 characters long.'
    )
);

此處的長度是 “字符串數據的字節數”。要小心,當處理非 ASCII 字符時,其值可能大於字符數。

static Validation::mimeType(mixed $checkarray $mimeTypes)

2.2 新版功能.

這條規則校驗有效的 mimeType

public $validate = array(
    'p_w_picpath' => array(
        'rule'    => array('mimeType', array('p_w_picpath/gif')),
        'message' => 'Invalid mime type.'
    ),
);
static Validation::minLength(string $checkinteger $min)

這條規則確保數據不低於最短長度。

public $validate = array(
    'login' => array(
        'rule'    => array('minLength', 8),
        'message' => 'Usernames must be at least 8 characters long.'
    )
);

此處的長度是 “字符串數據的字節數”。要小心,當處理非 ASCII 字符時,其值可能大於字符數。

static Validation::money(string $checkstring $symbolPosition = 'left')

這條規則確保值是一個有效的貨幣額。

第二個參數定義了貨幣符號的位置(左/右)。

public $validate = array(
    'salary' => array(
        'rule'    => array('money', 'left'),
        'message' => 'Please supply a valid monetary amount.'
    )
);
static Validation::multiple(mixed $checkmixed $options = array())

這條規則用於校驗 多 select input 表單。所支持的參數有 “in”、”max” 和 “min”。

public $validate = array(
    'multiple' => array(
        'rule' => array('multiple', array(
            'in'  => array('do', 'ray', 'me', 'fa', 'so', 'la', 'ti'),
            'min' => 1,
            'max' => 3
        )),
        'message' => 'Please select one, two or three options'
    )
);
static Validation::notEmpty(mixed $check)

這條規則確保列不是空的。

public $validate = array(
    'title' => array(
        'rule'    => 'notEmpty',
        'message' => 'This field cannot be left blank'
    )
);

不要在校驗 多選擇的 select input 時使用這條規則,因爲這會引起錯誤。請使用 “multiple” 代替。

static Validation::numeric(string $check)

校驗傳遞的數據是不是有效的數字。

public $validate = array(
    'cars' => array(
        'rule'    => 'numeric',
        'message' => 'Please supply the number of cars.'
    )
);
static Validation::naturalNumber(mixed $checkboolean $allowZero = false)

2.2 新版功能.

這條規則檢查傳遞的數據是不是有效的自然數。如果 $allowZero 被設置爲 true,0 也將是可以接受的值。

public $validate = array(
    'wheels' => array(
        'rule'    => 'naturalNumber',
        'message' => 'Please supply the number of wheels.'
    ),
    'airbags' => array(
        'rule'    => array('naturalNumber', true),
        'message' => 'Please supply the number of airbags.'
    ),
);
static Validation::phone(mixed $checkstring $regex = nullstring $country = 'all')

電話校驗針對的是美國電話號碼。如果想要校驗非美國電話號碼,可以提供一個正則表達式作爲第二個參數,以覆蓋額外的號碼格式。

public $validate = array(
    'phone' => array(
        'rule' => array('phone', null, 'us')
    )
);
static Validation::postal(mixed $checkstring $regex = nullstring $country = 'us')

郵政編碼針對的是美國、加拿大、英國、意大利、德國和比利時。對於其它的郵政編碼,可以提供一個正則作爲第二個參數。

public $validate = array(
    'zipcode' => array(
        'rule' => array('postal', null, 'us')
    )
);
static Validation::range(string $checkinteger $lower = nullinteger $upper = null)

這條規則確保傳遞的值在給定的範圍內。如果沒有提供範圍,這條規則檢測並確認傳遞的是當前平臺上的合法值。

public $validate = array(
    'number' => array(
        'rule'    => array('range', -1, 11),
        'message' => 'Please enter a number between 0 and 10'
    )
);

上例將接受大於 0 (例如 0.01)並且小於 10 (例如 9.99)的值。

註解

範圍的 上/下 限是不包含在內的。

static Validation::ssn(mixed $checkstring $regex = nullstring $country = null)

Ssn 校驗美國、丹麥和荷蘭的社會安全號碼。對於其它的社會安全號碼,需要提供一個正則表達式。

public $validate = array(
    'ssn' => array(
        'rule' => array('ssn', null, 'us')
    )
);
static Validation::time(string $check)

時間校驗判斷傳遞的字符串是不是有效的時間。格式有兩種 24 小時制(HH:MM)或者 上/下午制([H]H:MM[a|p]m)。不允許有秒,也不校驗秒。

static Validation::uploadError(mixed $check)

2.2 新版功能.

這條規則檢測文件上傳是否發生了錯誤。

public $validate = array(
    'p_w_picpath' => array(
        'rule'    => 'uploadError',
        'message' => 'Something went wrong with the upload.'
    ),
);
static Validation::url(string $checkboolean $strict = false)

這條規則檢測 URL 格式是否有效。支持 http(s)、ftp(s)、file、news 和 gopher 協議:

public $validate = array(
    'website' => array(
        'rule' => 'url'
    )
);

要確保協議是 url,可以啓用嚴格模式,示例如下:

public $validate = array(
    'website' => array(
        'rule' => array('url', true)
    )
);
static Validation::userDefined(mixed $checkobject $objectstring $methodarray $args = null)

運行一個用戶定義的校驗。

static Validation::uuid(string $check)

檢測值是否是有效的 uuid: http://tools.ietf.org/html/rfc4122

本地化校驗

phone() 和 postal() 校驗規則將所有它們不知道如何處理的國家前綴傳遞給帶有正確名稱的其它類。 例如,如果你住在荷蘭,可以創建如下類:

class NlValidation {
    public static function phone($check) {
        // ...
    }
    public static function postal($check) {
        // ...
    }
}

這個文件可以放在 APP/Validation/ 或 App/PluginName/Validation/,但是在嘗試使用它之前必須先用 App::uses() 導入。 可以用如下方式在校驗類中使用 NLValidation 類:

public $validate = array(
    'phone_no' => array('rule' => array('phone', null, 'nl')),
    'postal_code' => array('rule' => array('postal', null, 'nl')),
);

當模型數據被校驗,Validation 會看到它不能處理的 nl 國家編碼,並嘗試委託給 NlValidation::postal(),將其返回值用作校驗 通過/失敗 的結果。 這個辦法允許你建立一個類來處理本地化子集或者本地化組。 獨立檢驗方法的用法沒有改變,其能力通過添加的其它校驗器傳遞。

小技巧

本地化插件已經包含了一些有用的規則: https://github.com/cakephp/localized 你也可以隨意貢獻你的本地化檢驗規則。

在控制器中校驗數據

雖然正常情況下,你只使用模型的 save 方法,偶爾你也希望只校驗數據而不保存它。 例如,你可能希望在把數據真實地保存到數據庫前,向用戶顯示一些附加信息。 此時的數據校驗與保存數據時的校驗稍有不同。

首先,將數據賦給模型:

$this->ModelName->set($this->request->data);

然後,使用模型的校驗方法檢測數據是否有效,如果有效返回 true,否則返回 false:

if ($this->ModelName->validates()) {
    // 數據有效的邏輯
} else {
    // 數據無效的邏輯
    $errors = $this->ModelName->validationErrors;
}

只使用模型中指定的校驗集的子集校驗模型是可取的。 例如,有一個帶有 first_name、last_name、email 和 password 的 User 模型。 想要在建立或編輯用戶時校驗全部四個列規則。 而在用戶登錄時只校驗 email 和 passowrd 規則。 可以通過傳遞選項數據指定要校驗的列來實現:

if ($this->User->validates(array('fieldList' => array('email', 'password')))) {
    // 有效
} else {
    // 無效
}

校驗方法調用 invalidFields 方法填充模型的 validationErrors 屬性。 invalidFields 方法同時返回這些數據:

$errors = $this->ModelName->invalidFields(); // 包含 validationErrors 數組

校驗錯誤列表在連續調用 invalidFields() 的過程中不會進行清理。 所以如果校驗在循環內進行,又想分隔錯誤集,就不要使用 invalidFields()。取而代之的是使用 validates() 方法並訪問模型的 validationErrors 屬性。

需要重點注意的是在數據校驗前必須將其賦給模型。 這和在保存方法中不同,保存方法允許數據作爲參數傳遞。 另外,謹記不必在調用 save 之前調用校驗,因爲 save 將在地、實際保存前自動校驗數據。

要校驗多個模型,使用下列方法:

if ($this->ModelName->saveAll($this->request->data, array('validate' => 'only'))) {
  // 無效
} else {
  // 有效
}

如果在保存前已經校驗了數據,可以關閉校驗以防止重複檢測:

if ($this->ModelName->saveAll($this->request->data, array('validate' => false))) {
    // 保存時不再校驗
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章