数据校验
对于任何应用程序,数据校验都是重要部分,因为它有助于确保模型中的数据遵守了应用程序的业务规则。 例如,你可能想要确保密码最少要有8位,或者确保用户名唯一。 定义校验规则使表单处理非常非常简单。
校验过程有许多不同的面。本节覆盖的是其中模型这一面。 即:在调用模型中的 save() 方法时发生了什么。 关于如何处理校验错误的显示的更多信息,参见: 表单助手。
数据校验的第一步是在模型中建立校验规则。这是用模型定义中的 Model::validate 数组实现的:
1 class User extends AppModel { 2 public $validate = array(); 3 }
在上面的示例中,$validate 数组被添加到 User 模型中,但数组不包含校验规则。 假设 users 表有 login、password、email 和 born 列,下面的示例展示了应用在这些列上的一些简单的校验规则:
1 class User extends AppModel { 2 public $validate = array( 3 'login' => 'alphaNumeric', 4 'email' => 'email', 5 'born' => 'date' 6 ); 7 }
上例展示了如何向模型列添加校验规则。对于 login 列,只接受字母和数字,email 必须是有效的邮件地址,born 必须是有效的日期。 如果提交的数据违反了定义的规则,这些校验规则定义能使 CakePHP 自动在表单中显示错误信息。
CakePHP 有许多校验规则,且易于使用。 一些内置的规则允许你校验 email、URL 和 信用卡数字的格式 - 我们稍后会讲到它们的细节。
下面是一个非常复杂的校验的示例,利用了一些内置的校验规则:
1 class User extends AppModel { 2 public $validate = array( 3 'login' => array( 4 'alphaNumeric' => array( 5 'rule' => 'alphaNumeric', 6 'required' => true, 7 'message' => 'Alphabets and numbers only' 8 ), 9 'between' => array( 10 'rule' => array('between', 5, 15), 11 'message' => 'Between 5 to 15 characters' 12 ) 13 ), 14 'password' => array( 15 'rule' => array('minLength', '8'), 16 'message' => 'Minimum 8 characters long' 17 ), 18 'email' => 'email', 19 'born' => array( 20 'rule' => 'date', 21 'message' => 'Enter a valid date', 22 'allowEmpty' => true 23 ) 24 ); 25 }
其中两条是为 login 定义的:它只能包含字母和数字,并且长度必须在5至15之间。 password 列必须不少于8位长。 email 必须是有效的邮件地址,并且 born 必须是有效的日期。 还要注意的是,怎样定义校验失败时显示特定的错误信息。
上面的例子中,单个列可以使用多个校验规则。如果内置的规则不能满足你的要求,你可以添加自己需要的校验规则。
现在你已经看到了数据校验的全景,让我们瞧瞧如何在模型中定义这些规则。有三种不同的方法:简单数组、每个列的单个规则、每个列的多个规则。
简单规则
顾名思义,这是定义校验规则最简单的方法。 这种方法定义规则是标准语法是:
1 public $validate = array('fieldName' => 'ruleName');
‘fieldName’ 是规则所适用的列的名字,‘ruleName’是预定义的规则名,例如 ‘alphaNumeric’、’email’ 或者 ‘isUnique’。
例如,要确保用户所提供的是格式正确的邮件地址,可以使用如下规则:
1 public $validate = array('user_email' => 'email');
每个列一个规则
这种定义手法对校验规则的工作有更好的控制。在我们讨论这个之前,先来看看向单个列添加一条规则的标准用法:
1 public $validate = array( 2 'fieldName1' => array( 3 'rule' => 'ruleName', // or: array('ruleName', 'param1', 'param2' ...) 4 'required' => true, 5 'allowEmpty' => false, 6 'on' => 'create', // or: 'update' 7 'message' => 'Your Error Message' 8 ) 9 );
‘rule’ 键是必须的。如果仅设置了 ‘required’ => true,表单验证将无法正确工作。因为 ‘required’ 不是实际的规则。
正如你看到的,每个列(上面只演示了一个列)与包含了如下五个键的数组关联:‘rule’、 ‘required’、 ‘allowEmpty’、 ‘on’ 和 ‘message’。让我们仔细地观察这几个键。
rule
‘rule’ 方法定义了校验方面并且指定了一个值或者一个数组。这个特定的 ‘rule’ 可能是模型中的一个方法的名字,核心 Validation 类的一个方法的名字,或者正则表达式。要了解关于默认规则的更多信息,请参见 内核核验规则。
如果 rule 不包含任何参数,’rule’ 可以是单个值,例如:
1 public $validate = array( 2 'login' => array( 3 'rule' => 'alphaNumeric' 4 ) 5 );
如果 rule 包含参数(例如 max,min 或者范围),’rule’ 将是一个数组:
1 public $validate = array( 2 'password' => array( 3 'rule' => array('minLength', 8) 4 ) 5 );
记住,用数组方式定义规则时,’rule’ 键是必须的。
required
这个键接受一个逻辑值、create 或者 update。将其设置为 true 将使这一列总是被必须的。设置为 create 或者update 将使这一列只在更新或创建操作时必须。如果 ‘required’ 等于 true,数组中必须提供此列。例如,如果定义如下校验规则:
1 public $validate = array( 2 'login' => array( 3 'rule' => 'alphaNumeric', 4 'required' => true 5 ) 6 );
传递给模型的 save() 方法的数据必须包含提供给 login 列的数据。如果它不存在,那么校验失败。这个键的默认值为逻辑 false。
required => true 与 校验规则中的 notEmpty() 不是一回事儿。required => true 表示这个数组 键 必须提供 - 不意味着它必须有值。如果数据集没有提供,校验失败,但是如果提交了空值(’‘)是有可能成功的(这依赖于规则的详细定义)。
在 2.1 版更改: 添加了对 create 和 update 的支持。
allowEmpty
如果设置为 false,这个列的值必须是 非空的,, the field value must be nonempty, 其中 “nonempty” 非空的定义为 !empty($value) || is_numeric($value)。 对于数值检测,当 $value 为0时,CakePHP 认为是正确的。
required 与 allowEmpty 的不同可能会造成混乱。'required' => true 意味着 $this->data 中不提供带有这个列的键 就不能保存模型; 而 'allowEmpty' => false 则像上面描述的寻,是确保这个列的 值 必须是非空的。
on
‘on’ 键可以被设置为 ‘update’ 或 ‘create’。它提供了允许一些规则应用于创建新记录的过程中或者更新记录的过程中的机制。
如果一条规则被定义成 ‘on’ => ‘create’,这条规则仅在创建新记录的过程中有效。类似的,如果它被定义成 ‘on’ => ‘update’,将只在更新记录的过程中有效。
‘on’ 的默认值为空(null)。当 ‘on’ 为空(null),这条规则在创建和更新过程中同时生效。
message
message 键为规则自定义校验错误时的显示信息:
1 public $validate = array( 2 'password' => array( 3 'rule' => array('minLength', 8), 4 'message' => 'Password must be at least 8 characters long' 5 ) 6 );
每个列多条规则
上面的技术为我们提供了比简单的规则分配更大的灵活性,再进一步,我们能获得更详细的数据校验控制。下面我们介绍一种允许我们为每个列赋予多个规则的技术。
想要为单个列赋多个校验规则,基本的写法如下:
1 public $validate = array( 2 'fieldName' => array( 3 'ruleName' => array( 4 'rule' => 'ruleName', 5 // 类似 on,required 等扩展键放在这里... 6 ), 7 'ruleName2' => array( 8 'rule' => 'ruleName2', 9 // 类似 on,required 等扩展键放在这里... 10 ) 11 ) 12 );
正像你看到的那样,这和上一节中所做的非常相似。在那儿,每个列仅有一个校验参数数组。在这儿,每个 ‘fieldName’ 是一个规则数组的索引。每个 ‘ruleName’ 包含一个校验参数数组。
下面是一个带有实际例子的更好诠释:
1 public $validate = array( 2 'login' => array( 3 'loginRule-1' => array( 4 'rule' => 'alphaNumeric', 5 'message' => 'Only alphabets and numbers allowed', 6 ), 7 'loginRule-2' => array( 8 'rule' => array('minLength', 8), 9 'message' => 'Minimum length of 8 characters' 10 ) 11 ) 12 );
上例为 login 列定义了两个规则: loginRule-1 和 loginRule-2。如你所见,每个规则的标识随意命名。
在为单个列定义多条规则时,’required’ 和 ‘allowEmpty’ 键仅需在第一个规则中使用一次。
last
对于每个列有多条规则的情况,默认的如果一个规则校验失败并返回错误消息,该列的后续规则将不再计算。如果希望一个规则失败了校验仍然继续,就将这条规则的 last 键设置为 false。
在下面的例子中,即使 “rule1” 失败,”rule2” 仍将计算,并且在 “rule2” 也失败的时候返回所有的错误信息:
1 public $validate = array( 2 'login' => array( 3 'rule1' => array( 4 'rule' => 'alphaNumeric', 5 'message' => 'Only alphabets and numbers allowed', 6 'last' => false 7 ), 8 'rule2' => array( 9 'rule' => array('minLength', 8), 10 'message' => 'Minimum length of 8 characters' 11 ) 12 ) 13 );
在用数组指定校验规则时,可以不使用 message 键。考虑下面的例子:
1 public $validate = array( 2 'login' => array( 3 'Only alphabets and numbers allowed' => array( 4 'rule' => 'alphaNumeric', 5 ), 6 ) 7 );
如果 alphaNumeric 规则失败,由于没有设置 message 键,这条规则的键 ‘Only alphabets and numbers allowed’ 将作为错误消息被返回。
自定义校验规则
如果找不到所需的校验规则,可以自定义。有两种方法进行自定义: 自定义正则表达式,或者创建自定义校验方法。
自定义校验正则表达式
如果所需的校验手段能够通过正则表达式匹配来完成,可以自定义表达式作为列的校验规则:
1 public $validate = array( 2 'login' => array( 3 'rule' => '/^[a-z0-9]{3,}$/i', 4 'message' => 'Only letters and integers, min 3 characters' 5 ) 6 );
上例检查了 login 是否仅包含字母和整数,并且不得小于3个字符。
“rule” 中的正则表达式必须用斜杠(/)括住。末尾的可选项 ‘i’ 表示正则表达式是不区分大小写的。
添加自己的校验方法
有时仅用正则模式校验数据还不够。 例如,想要确保促销码仅能被使用 25 次,需要添加自己的校验方法,示例如下:
1 class User extends AppModel { 2 3 public $validate = array( 4 'promotion_code' => array( 5 'rule' => array('limitDuplicates', 25), 6 'message' => 'This code has been used too many times.' 7 ) 8 ); 9 10 public function limitDuplicates($check, $limit) { 11 // $check 的值: array('promotion_code' => 'some-value') 12 // $limit 的值: 25 13 $existing_promo_count = $this->find('count', array( 14 'conditions' => $check, 15 'recursive' => -1 16 )); 17 return $existing_promo_count < $limit; 18 } 19 }
被校验的当前列被传递给函数,作为该函数的第一个参数,是以列名为键,以 post 来的数据为值构成的关联数组。
如果想要给校验函数传递额外的参数,向 ‘rule’ 数组添加一个元素,并在函数中以扩展参数来处理它们(排在主参数$check 之后)。
校验函数可以放在模型中(就像上面的例子),也可以放在模型实现的行为中。包括映射方法。
模型/行为 方法最先校验,优先于在 Validation 类的方法。这意味着可以在应用程序级别(通过在 AppModel 添加方法)或模型级别覆盖已存在的校验方法(例如 alphaNumeric())。
在编写可用于多个列的校验规则,从 $check 数组中提取列值时要小心。$check 数组是以表单域名作为键、表单域值作为值构成的。存储在 $this->data 成员变量中的整个记录被校验。
1 class Post extends AppModel { 2 3 public $validate = array( 4 'slug' => array( 5 'rule' => 'alphaNumericDashUnderscore', 6 'message' => 'Slug can only be letters, numbers, dash and underscore' 7 ) 8 ); 9 10 public function alphaNumericDashUnderscore($check) { 11 // $data 数组是以表单域名为键被传递的 12 // 必须提取该值以使函数通用 13 $value = array_values($check); 14 $value = $value[0]; 15 16 return preg_match('|^[0-9a-zA-Z_-]*$|', $value); 17 } 18 }
注解
自定义的校验方法的可见性必须是 public。不支持 protected 和 private 级别的校验方法。
如果规则有效,该方法返回 true。如果校验失败,返回 false。另一个有效的返回值是一个字符串,它是要显示的错误信息。返回字符串意味着校验失败。 这个字符串将覆盖 $validate 数组中的信息集,并将作为列为什么无效的原因显示在视图的表单中。
动态改变校验规则
使用 $validate 属性定义校验规则是为每个模型定义静态规则的好办法。不过有时你需要从预定义的规则集中动态添加、改变或删除校验规则。
所有的校验规则都存储在 ModelValidator 对象中,它掌握着模型中各个列的每个规则集。 通过通知这个对象为想要的列存储新的校验方法来定义新的校验规则是很简单的。
添加新的校验规则
2.2 新版功能.
ModelValidator 对象提供了数个向集中添加新列的途径。第一个是使用 add 方法:
1 // 在模型类中 2 $this->validator()->add('password', 'required', array( 3 'rule' => 'notEmpty', 4 'required' => 'create' 5 ));
这样就会为模型中的 password 列添加单一规则。可以链式多次调用 add 来创建多条所需的规则:
1 // 在模型类中 2 $this->validator() 3 ->add('password', 'required', array( 4 'rule' => 'notEmpty', 5 'required' => 'create' 6 )) 7 ->add('password', 'size', array( 8 'rule' => array('between', 8, 20), 9 'message' => 'Password should be at least 8 chars long' 10 ));
也可以一次性为单个列添加多条规则:
1 $this->validator()->add('password', array( 2 'required' => array( 3 'rule' => 'notEmpty', 4 'required' => 'create' 5 ), 6 'size' => array( 7 'rule' => array('between', 8, 20), 8 'message' => 'Password should be at least 8 chars long' 9 ) 10 ));
或者也可以利用数组接口使用此对象,直接为列设置规则:
1 $validator = $this->validator(); 2 $validator['username'] = array( 3 'unique' => array( 4 'rule' => 'isUnique', 5 'required' => 'create' 6 ), 7 'alphanumeric' => array( 8 'rule' => 'alphanumeric' 9 ) 10 );
编辑现有的校验规则
2.2 新版功能.
可以使用 validator 对象编辑现有的校验规则,有几种方法可以修改现有规则、向列追加方法或者从列规则集中完整地删除一条规则:
1 // 在模型类中 2 $this->validator()->getField('password')->setRule('required', array( 3 'rule' => 'required', 4 'required' => true 5 ));
也可以使用类似的方法完整地替换一个列的所有规则:
1 // 在模型类中 2 $this->validator()->getField('password')->setRules(array( 3 'required' => array(...), 4 'otherRule' => array(...) 5 ));
如果只是想领回规则中的单个属性,可以直接设置 CakeValidationRule 对象的属性:
1 // 在模型类中 2 $this->validator()->getField('password') 3 ->getRule('required')->message = 'This field cannot be left blank';
CakeValidationRule 中的属性是由在模型中使用 $validate 属性定义相应规则的有效数组键来命名的。
在向规则集中添加规则时,也可以使用数组接口编辑已有的规则:
1 $validator = $this->validator(); 2 $validator['username']['unique'] = array( 3 'rule' => 'isUnique', 4 'required' => 'create' 5 ); 6 7 $validator['username']['unique']->last = true; 8 $validator['username']['unique']->message = 'Name already taken';
从规则集中删除规则
2.2 新版功能.
完整地删除一个列的所有规则和只删除一个列规则集中的单个规则都是可以的:
1 // 完成地删除一个列的所有规则 2 $this->validator()->remove('username'); 3 4 // 从 password 中删除 'required' 规则 5 $this->validator()->remove('password', 'required');
还可以使用数组接口从规则集中删除规则:
1 $validator = $this->validator(); 2 // 完整地删除一个列的所有规则 3 unset($validator['username']); 4 5 // 从 passworkd 中删除 'required' 规则 6 unset($validator['password']['required']);
内核核验规则
- class Validation
CakePHP 的 Validation 类包含许多能使模型数据校验更容易的校验规则。这个类包含许多常用的不需要自己编写的校验技术。 下面是全部规则的完整列表及其用法示例。
- static Validation:: alphaNumeric ( mixed $check )
-
列数据必须只包含字母和数字。
1 public $validate = array( 2 'login' => array( 3 'rule' => 'alphaNumeric', 4 'message' => 'Usernames must only contain letters and numbers.' 5 ) 6 );
- static Validation:: between ( string $check, integer $min, integer $max )
-
列的数据长度必须位于指定的数值范围。必须同时提供最小值和最大值。Uses = not.:
1 public $validate = array( 2 'password' => array( 3 'rule' => array('between', 5, 15), 4 'message' => 'Passwords must be between 5 and 15 characters long.' 5 ) 6 );
数据的长度是指”字符串数据的字节数”。要小心,当处理非 ASCII 字符时,其值可能大于字符数。
- static Validation:: blank ( mixed $check )
-
这条规则用于确保列值为空或者其值仅包含空白字符。空白字符包括 空格、tab、回车和换行。
1 public $validate = array( 2 'id' => array( 3 'rule' => 'blank', 4 'on' => 'create' 5 ) 6 );
- static Validation:: boolean ( string $check )
-
列数据必须是逻辑值。有效值包括 true 或 false,整数值 0 或 1,字符串值 ‘0’ 或 ‘1’。
1 public $validate = array( 2 'myCheckbox' => array( 3 'rule' => array('boolean'), 4 'message' => 'Incorrect value for myCheckbox' 5 ) 6 );
- static Validation:: cc ( mixed $check, mixed $type = 'fast', boolean $deep = false, string $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’键允许提供自定义的用于校验信用卡编号的正则表达式:
1 public $validate = array( 2 'ccnumber' => array( 3 'rule' => array('cc', array('visa', 'maestro'), false, null), 4 'message' => 'The credit card number you supplied was invalid.' 5 ) 6 );
- static Validation:: comparison ( mixed $check1, string $operator = null, integer $check2 = null )
-
Comparison 用于比较数字值。支持 “is greater”、”isless”、”greater or equal”、”less or equal”、”equal to” 和 “not equal”。以下为示例:
1 public $validate = array( 2 'age' => array( 3 'rule' => array('comparison', '>=', 18), 4 'message' => 'Must be at least 18 years old to qualify.' 5 ) 6 ); 7 8 public $validate = array( 9 'age' => array( 10 'rule' => array('comparison', 'greater or equal', 18), 11 'message' => 'Must be at least 18 years old to qualify.' 12 ) 13 );
- static Validation:: custom ( mixed $check, string $regex = null )
-
用于自定义正则表达式:
1 public $validate = array( 2 'infinite' => array( 3 'rule' => array('custom', '\u221E'), 4 'message' => 'Please enter an infinite number.' 5 ) 6 );
- static Validation:: date ( string $check, mixed $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’:
1 public $validate = array( 2 'born' => array( 3 'rule' => array('date', 'ymd'), 4 'message' => 'Enter a valid date in YY-MM-DD format.', 5 'allowEmpty' => true 6 ) 7 );
当许多数据需要用一个特定的格式存储时,你可能会考虑接受较宽泛的格式并转换,而不是强制用户提供一个指定的格式。你可以为客户做的更多、更好!
- static Validation:: datetime ( array $check, mixed $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’:
1 public $validate = array( 2 'birthday' => array( 3 'rule' => array('datetime', 'dmy'), 4 'message' => 'Please enter a valid date and time.' 5 ) 6 );
可以通过传递第二个参数来指定自定义正则表达式。如果使用此参数,就以此为标准进行验证。
与 date() 不同,datetime() 校验日期和时间。
- static Validation:: decimal ( integer $check, integer $places = null, string $regex = null )
-
这条规则确保数据是有效的数字。可以传递一个指定小数点后的数字位数的参数。如果没有传递参数,数据必须是严格意义上的浮点数,如果没有在小数点后发现数字,校验就会失败:
1 public $validate = array( 2 'price' => array( 3 'rule' => array('decimal', 2) 4 ) 5 );
- static Validation:: email ( string $check, boolean $deep = false, string $regex = null )
-
这条规则校验数据是否为有效的邮件地址。传递一个逻辑值作为其第二个参数,这条规则将试图检查地址中的主机是否是有效的:
1 public $validate = array('email' => array('rule' => 'email')); 2 3 public $validate = array( 4 'email' => array( 5 'rule' => array('email', true), 6 'message' => 'Please supply a valid email address.' 7 ) 8 );
- static Validation:: equalTo ( mixed $check, mixed $compareTo )
-
这条规则确保数据与给定的值类型相同、数值相等。
1 public $validate = array( 2 'food' => array( 3 'rule' => array('equalTo', 'cake'), 4 'message' => 'This value must be the string cake' 5 ) 6 );
- static Validation:: extension ( mixed $check, array $extensions = array('gif', 'jpeg', 'png', 'jpg') )
-
这条规则校验文件扩展名是不是 .jpg 或者 .png。允许以数组方式传递多个扩展名。
1 public $validate = array( 2 'image' => array( 3 'rule' => array('extension', array('gif', 'jpeg', 'png', 'jpg')), 4 'message' => 'Please supply a valid image.' 5 ) 6 );
- static Validation:: fileSize ( $check, $operator = null, $size = null )
-
这条规则允许检测文件长度。可以使用 $operator 来决定所需的比较类型。所有 comparison() 支持的操作这里也支持。 此方法将通过读取 tmp_name 键(如果 $check 是一个包含该键的数组)自动处理来自 $_FILES 的数组值:
1 public $validate = array( 2 'image' => array( 3 'rule' => array('filesize', '<=', '1MB'), 4 'message' => 'Image must be less than 1MB' 5 ) 6 );
2.3 新版功能: 此方法是 2.3 版增加的。
- static Validation:: inList ( string $check, array $list )
-
这条规则确保值在给定的集合中。它需要一个值数组。如果列值与给定的数组中的某个值匹配,则列被视为有效。
例如:
1 public $validate = array( 2 'function' => array( 3 'allowedChoice' => array( 4 'rule' => array('inList', array('Foo', 'Bar')), 5 'message' => 'Enter either Foo or Bar.' 6 ) 7 ) 8 );
- static Validation:: ip ( string $check, string $type = 'both' )
-
这条规则确保被提交的是有效的 IPv4 或 IPv6 地址。接受参数 ‘both’ (默认值)、’IPv4’ 或者 ‘IPv6’。
1 public $validate = array( 2 'clientip' => array( 3 'rule' => array('ip', 'IPv4'), // or 'IPv6' or 'both' (default) 4 'message' => 'Please supply a valid IP address.' 5 ) 6 );
- static Validation:: isUnique
-
列数据必须唯一,不能是被其它行用过的。
1 public $validate = array( 2 'login' => array( 3 'rule' => 'isUnique', 4 'message' => 'This username has already been taken.' 5 ) 6 );
- static Validation:: luhn ( string|array $check, boolean $deep = false )
-
Luhn 算法:各种标识码的校验算法。更多信息参见 http://en.wikipedia.org/wiki/Luhn_algorithm 。
- static Validation:: maxLength ( string $check, integer $max )
-
这条规则确保数据在最大长度范围内。
1 public $validate = array( 2 'login' => array( 3 'rule' => array('maxLength', 15), 4 'message' => 'Usernames must be no larger than 15 characters long.' 5 ) 6 );
此处的长度是 “字符串数据的字节数”。要小心,当处理非 ASCII 字符时,其值可能大于字符数。
- static Validation:: mimeType ( mixed $check, array $mimeTypes )
-
2.2 新版功能.
这条规则校验有效的 mimeType
1 public $validate = array( 2 'image' => array( 3 'rule' => array('mimeType', array('image/gif')), 4 'message' => 'Invalid mime type.' 5 ), 6 );
- static Validation:: minLength ( string $check, integer $min )
-
这条规则确保数据不低于最短长度。
1 public $validate = array( 2 'login' => array( 3 'rule' => array('minLength', 8), 4 'message' => 'Usernames must be at least 8 characters long.' 5 ) 6 );
此处的长度是 “字符串数据的字节数”。要小心,当处理非 ASCII 字符时,其值可能大于字符数。
- static Validation:: money ( string $check, string $symbolPosition = 'left' )
-
这条规则确保值是一个有效的货币额。
第二个参数定义了货币符号的位置(左/右)。
1 public $validate = array( 2 'salary' => array( 3 'rule' => array('money', 'left'), 4 'message' => 'Please supply a valid monetary amount.' 5 ) 6 );
- static Validation:: multiple ( mixed $check, mixed $options = array() )
-
这条规则用于校验 多 select input 表单。所支持的参数有 “in”、”max” 和 “min”。
1 public $validate = array( 2 'multiple' => array( 3 'rule' => array('multiple', array( 4 'in' => array('do', 'ray', 'me', 'fa', 'so', 'la', 'ti'), 5 'min' => 1, 6 'max' => 3 7 )), 8 'message' => 'Please select one, two or three options' 9 ) 10 );
- static Validation:: notEmpty ( mixed $check )
-
这条规则确保列不是空的。
1 public $validate = array( 2 'title' => array( 3 'rule' => 'notEmpty', 4 'message' => 'This field cannot be left blank' 5 ) 6 );
不要在校验 多选择的 select input 时使用这条规则,因为这会引起错误。请使用 “multiple” 代替。
- static Validation:: numeric ( string $check )
-
校验传递的数据是不是有效的数字。
1 public $validate = array( 2 'cars' => array( 3 'rule' => 'numeric', 4 'message' => 'Please supply the number of cars.' 5 ) 6 );
- static Validation:: naturalNumber ( mixed $check, boolean $allowZero = false )
-
2.2 新版功能.
这条规则检查传递的数据是不是有效的自然数。如果 $allowZero 被设置为 true,0 也将是可以接受的值。
1 public $validate = array( 2 'wheels' => array( 3 'rule' => 'naturalNumber', 4 'message' => 'Please supply the number of wheels.' 5 ), 6 'airbags' => array( 7 'rule' => array('naturalNumber', true), 8 'message' => 'Please supply the number of airbags.' 9 ), 10 );
- static Validation:: phone ( mixed $check, string $regex = null, string $country = 'all' )
-
电话校验针对的是美国电话号码。如果想要校验非美国电话号码,可以提供一个正则表达式作为第二个参数,以覆盖额外的号码格式。
1 public $validate = array( 2 'phone' => array( 3 'rule' => array('phone', null, 'us') 4 ) 5 );
- static Validation:: postal ( mixed $check, string $regex = null, string $country = 'us' )
-
邮政编码针对的是美国、加拿大、英国、意大利、德国和比利时。对于其它的邮政编码,可以提供一个正则作为第二个参数。
1 public $validate = array( 2 'zipcode' => array( 3 'rule' => array('postal', null, 'us') 4 ) 5 );
- static Validation:: range ( string $check, integer $lower = null, integer $upper = null )
-
这条规则确保传递的值在给定的范围内。如果没有提供范围,这条规则检测并确认传递的是当前平台上的合法值。
1 public $validate = array( 2 'number' => array( 3 'rule' => array('range', -1, 11), 4 'message' => 'Please enter a number between 0 and 10' 5 ) 6 );
上例将接受大于 0 (例如 0.01)并且小于 10 (例如 9.99)的值。
注解
范围的 上/下 限是不包含在内的。
- static Validation:: ssn ( mixed $check, string $regex = null, string $country = null )
-
Ssn 校验美国、丹麦和荷兰的社会安全号码。对于其它的社会安全号码,需要提供一个正则表达式。
1 public $validate = array( 2 'ssn' => array( 3 'rule' => array('ssn', null, 'us') 4 ) 5 );
- static Validation:: time ( string $check )
-
时间校验判断传递的字符串是不是有效的时间。格式有两种 24 小时制(HH:MM)或者 上/下午制([H]H:MM[a|p]m)。不允许有秒,也不校验秒。
- static Validation:: uploadError ( mixed $check )
-
2.2 新版功能.
这条规则检测文件上传是否发生了错误。
1 public $validate = array( 2 'image' => array( 3 'rule' => 'uploadError', 4 'message' => 'Something went wrong with the upload.' 5 ), 6 );
- static Validation:: url ( string $check, boolean $strict = false )
-
这条规则检测 URL 格式是否有效。支持 http(s)、ftp(s)、file、news 和 gopher 协议:
1 public $validate = array( 2 'website' => array( 3 'rule' => 'url' 4 ) 5 );
要确保协议是 url,可以启用严格模式,示例如下:
1 public $validate = array( 2 'website' => array( 3 'rule' => array('url', true) 4 ) 5 );
- static Validation:: userDefined ( mixed $check, object $object, string $method, array $args = null )
-
运行一个用户定义的校验。
- static Validation:: uuid ( string $check )
-
检测值是否是有效的 uuid: http://tools.ietf.org/html/rfc4122
本地化校验
phone() 和 postal() 校验规则将所有它们不知道如何处理的国家前缀传递给带有正确名称的其它类。 例如,如果你住在荷兰,可以创建如下类:
1 class NlValidation { 2 public static function phone($check) { 3 // ... 4 } 5 public static function postal($check) { 6 // ... 7 } 8 }
这个文件可以放在 APP/Validation/ 或 App/PluginName/Validation/,但是在尝试使用它之前必须先用 App::uses() 导入。 可以用如下方式在校验类中使用 NLValidation 类:
1 public $validate = array( 2 'phone_no' => array('rule' => array('phone', null, 'nl')), 3 'postal_code' => array('rule' => array('postal', null, 'nl')), 4 );
当模型数据被校验,Validation 会看到它不能处理的 nl 国家编码,并尝试委托给 NlValidation::postal(),将其返回值用作校验 通过/失败 的结果。 这个办法允许你建立一个类来处理本地化子集或者本地化组。 独立检验方法的用法没有改变,其能力通过添加的其它校验器传递。
小技巧
本地化插件已经包含了一些有用的规则: https://github.com/cakephp/localized 你也可以随意贡献你的本地化检验规则。
虽然正常情况下,你只使用模型的 save 方法,偶尔你也希望只校验数据而不保存它。 例如,你可能希望在把数据真实地保存到数据库前,向用户显示一些附加信息。 此时的数据校验与保存数据时的校验稍有不同。
首先,将数据赋给模型:
1 $this->ModelName->set($this->request->data);
然后,使用模型的校验方法检测数据是否有效,如果有效返回 true,否则返回 false:
1 if ($this->ModelName->validates()) { 2 // 数据有效的逻辑 3 } else { 4 // 数据无效的逻辑 5 $errors = $this->ModelName->validationErrors; 6 }
只使用模型中指定的校验集的子集校验模型是可取的。 例如,有一个带有 first_name、last_name、email 和 password 的 User 模型。 想要在建立或编辑用户时校验全部四个列规则。 而在用户登录时只校验 email 和 passowrd 规则。 可以通过传递选项数据指定要校验的列来实现:
1 if ($this->User->validates(array('fieldList' => array('email', 'password')))) { 2 // 有效 3 } else { 4 // 无效 5 }
校验方法调用 invalidFields 方法填充模型的 validationErrors 属性。 invalidFields 方法同时返回这些数据:
1 $errors = $this->ModelName->invalidFields(); // 包含 validationErrors 数组
校验错误列表在连续调用 invalidFields() 的过程中不会进行清理。 所以如果校验在循环内进行,又想分隔错误集,就不要使用 invalidFields()。取而代之的是使用 validates() 方法并访问模型的 validationErrors 属性。
需要重点注意的是在数据校验前必须将其赋给模型。 这和在保存方法中不同,保存方法允许数据作为参数传递。 另外,谨记不必在调用 save 之前调用校验,因为 save 将在地、实际保存前自动校验数据。
要校验多个模型,使用下列方法:
1 if ($this->ModelName->saveAll($this->request->data, array('validate' => 'only'))) { 2 // 无效 3 } else { 4 // 有效 5 }
如果在保存前已经校验了数据,可以关闭校验以防止重复检测:
1 if ($this->ModelName->saveAll($this->request->data, array('validate' => false))) { 2 // 保存时不再校验 3 }