Validation 类別

类別幫助你驗證使用者輸入,如果你想要同時建立一个表单&它的驗證, 使用 Fieldset 类別代替。

配置

Validation 类別可以選擇性的透過全域应用程序配置档案 app/config/config.php 來配置。定義一个名为 'validation' 的段落,在其中以下設定可以被定義:

變数 类型 預設 描述
no_errors 字串
''
如果沒有发现驗證错误要回傳的字串。
open_list 字串
'<ul>'
要被附加到错误列表前的字串。通常这是某種形式的 HTML 來格式化列表。預設情況下,它被格式化为一个無序列表。
close_list 字串
'</ul>'
要被附加到错误列表後的字串。
open_error 字串
'<li>'
要被附加到每个单一错误訊息前的字串。
close_error 字串
'</li>'
要被附加到每个单一错误訊息後的字串。
quote_label 布林
false
如果为 true,而且驗證欄位的标籤包含空白,該标籤会被括在雙引號中,以增強可讀性。
global_input_fallback 布林
true
如果为 true,而且值在輸入陣列找不到,該值将退回到 Input::param。

如果全域配置中缺少这些值中的一个或多个時,类別将使用定義在这張表中的預設值。

用法

要開始驗證你需要建立一个物件,这可以是名为 "default" 的預設物件, 或者你可以命名它如果你需要多个驗證物件。

// 使用預設
$val = Validation::forge();

// ……或給它命名
$val = Validation::forge('my_validation');

在让它實例化之後,你可以開始添加欄位給它。这與使用 Fieldset 类別的運作完全一樣, 然而这裡我們只記錄首選的用法。

$val = Validation::forge('my_validation');

// 添加一个 username 欄位,給它 "Your username" 标籤并让它为必要
$val->add('username', 'Your username')->add_rule('required');

// 现在添加另一个 password 欄位,并让它必須包含至少 3 个最多 10 个字元
$val->add('password', 'Your password')->add_rule('required')
    ->add_rule('min_length', 3)
    ->add_rule('max_length', 10);

// 现在为 gender 添加另一个欄位,并要求它包含 "M" 或 "F" 其中之一。
$val->add('gender', 'Your gender')->add_rule('required')
    ->add_rule('match_collection', array('M', 'F'));

add_rule() 方法的第一參数除了提供的驗證方法之外,可以包含 PHP 原生函式名稱、任何有效的 PHP 回呼(callback)和閉包(Closure)。該方法会取得要被驗證做为其第一參数的值, 以及任何更多可以給 add_rule() 方法的參数值。

我們也提供了更短的語法,相對这非常受限。它不会接受陣列回呼(array-callback)、 閉包(closure)或字串以外的參数。你也不能在你的形式中使用管道符號(|)當你使用 'match_pattern'規則, 因为該符號被用來拆分定義的規則。

// 與上面範例相同的欄位
$val = Validation::forge('my_validation');
$val->add_field('username', 'Your username', 'required');
$val->add_field('password', 'Your password', 'required|min_length[3]|max_length[10]');
$val->add_field('gender', 'Your gender', 'required|match_collection[M,F]');

一旦所有欄位都被添加,你可以执行你的驗證。这将預設为 $_POST 輸入, 但可以在給一个輸入陣列時被擴充并覆寫。

// 执行剛发布的驗證
if ($val->run())
{
	// 在驗證成功時处理你的東西
}
else
{
	// 驗證失敗
}

// 替代上面,覆寫 POST 中的 username,password 仍在 POST 中被徵詢
if ($val->run(array('username' => 'something')))

在驗證执行後,有三个關於輸入資訊的可用方法:

// 取得一个驗證成功欄位 => 值配對的陣列
$vars = $val->validated();
// 取得一个驗證错误为欄位 => 错误配對的陣列
$errors = $val->error();
// 取得一个已驗證輸入的陣列,这合併了 post 和給 run() 的輸入
$input = $val->input();

// 这些方法也都可以只取得单一欄位的值
$var = $val->validated('username');

驗證也可以部份执行,在这種情況下甚至 required 欄位会被忽略,當他們不在 POST 中或輸入給 run()。 透過設定执行的第二參数为 true 能做到。

// 这会只驗證 password,當 username 沒有出现在 POST 時
$val->run(array('password' => 'whatever'), true);

驗證規則

請注意,所有方法(甚至 min_length)在空白輸入時也会回傳 true。 也要要求欄位你應該添加 "required" 規則。

这些規則都可以像以下这樣被使用:

// 一般使用範例,一个沒參数的規則,和另一个有參数的規則
$val->add('email', 'Email address')->add_rule('match_value', 'me@mydomain.com', true)->add_rule('valid_email');
$val->add_field('email', 'Email address', 'match_value[me@mydomain.com,1]|valid_email');

規則表

規則 額外參数 描述
required (無) 該欄位必須被設定并給一些不是 nullfalse 或空字串的值。
required_with $fieldname 如果所給的 $fieldname 欄位被設定,該欄位必須被設定。
match_value $compare, $strict = false 該欄位輸入必須符合 $compare,会使用 == 做,除非第二參数也給 true (那麼会使用 ===)。
match_pattern $pattern 会嘗试針對所給 $pattern(必須是完整 PREG 正規表達式)相配值。

注意:不能 在你的形式中使用管道符號(|)當你使用短語法,因为該符號被用來在字串中拆分規則。

match_field $field 会嘗试相配該欄位與所給名稱的欄位, 相配会使用 ===。

重要:你只能針對此規則添加到欄位之前的欄位進行相配。

match_collection $collection = array() 会试著針對集合的有效值進行欄位匹配。
min_length $length 测试該字串是否包含至少 $length 的字元数。
max_length $length 测试該字串是否包含不超過 $length 的字元数。
exact_length $length 测试該字串是否有准確 $length 的字元数。
valid_date $format, $strict = true 驗證所給輸入是否为有效的日期格式。如果有給 $format 參数,驗證会使用指定格式。 会嚴格(例如:閏年)檢查除非第二參数是給 false。
valid_email (無) 驗證所給輸入是否为有效的 Email 地址。
valid_emails $separator(選擇性) 驗證多个以逗號(或 $separator)分隔的 Email 地址。
valid_url (無) 驗證所給輸入是否是有效的 URL。
valid_ip (無) 驗證所給輸入是否是有效的 IP。
numeric_min $min_val 测试所給輸入是否是一个大於 $min_val 的数字, 它不檢查或轉化輸入为数字值,所以任何非数字值会被認为是 0。 使用 PHP 函式 is_numeric 先行檢查。
numeric_max $max_val 测试所給輸入是否是一个小於 $max_val的数字。 (關於非数字值詳見 numeric_min 規則)
numeric_between $min_val, $max_val 测试所給輸入是否是一个在 $min_val$max_val 之間的数字。 (關於非数字值詳見 numeric_min 規則)

重要:指定的號码包含在範圍中。

valid_string $flags = array('alpha', 'utf8') 見以下。

有效字串規則

驗證字串是否堅持 $flags 參数設定的條件。 接受的标誌有:

标誌 描述
alpha 允許字母字元。
uppercase 與只允許大寫字元字母的組合使用。
lowercase 與只允許小寫字元字母的組合使用。
numeric 允許数字字元。
spaces 允許一般空白。
newlines 允許換行符號。
tabs 允許 tab。
dots 允許點。
commas 允許逗號。
punctuation 允許點、逗號、驚嘆號、問號、冒號和分號。
dashes 允許破折號和底線。
singlequotes 允許单引號。
doublequotes 允許雙引號。
quotes 允許单引號和雙引號。
forwardslashes 允許正斜線。
backwardslashes 允許反斜線。
slashes 所有正反斜線。
brackets 允許開啟和關閉的括號。
braces 允許開啟和關閉的大括號。
utf8 添加 UTF8 修飾符到正規表達式。

擴充 Validation 类別

擴充 Validation 类別有幾種辦法:

1. 擴充核心类別像擴充核心类別中的敘述

2. 在 app/classes/myrules.php 中建立一个类別(例如)

// app/classes/myrules.php
class MyRules
{
	// 注意这是一个靜態方法
	public static function _validation_unique($val, $options)
	{
		list($table, $field) = explode('.', $options);

		$result = DB::select(DB::expr("LOWER (\"$field\")"))
		->where($field, '=', Str::lower($val))
		->from($table)->execute();

		return ! ($result->count() > 0);
	}

	// 注意这是一个非靜態方法
	public function _validation_is_upper($val)
	{
		return $val === strtoupper($val);
	}

}

// 并且像这樣呼叫它:
$val = Validation::forge();

// 注意靜態與非靜態驗證規則之間的差異:

// 靜態地添加,将只能使用靜態方法
$val->add_callable('MyRules');

// 非靜態地添加,将可以使用靜態與非靜態方法
$val->add_callable(new MyRules());

$val->add('username', 'Your username', array(), array('trim', 'strip_tags', 'required', 'is_upper'))
	->add_rule('unique', 'users.username');

3. 從模型呼叫回呼(callback),它運作就像上面所描述的方法,但我們只需要用其他方式呼叫它:

$val = Validation::forge();
$val->add_model('Model_User');

注意: 你需要用於方法的 '_validation_' 前綴以在驗證中是可用的。

注意: 如果你傳遞类別名稱做为一个字串,驗證方法必須被定義为靜態。如果方法不是靜態,你将必須傳遞一个物件實例做为 callable()。

使用 Validation::active()Validation::active_field() 來分別取得目前活躍的 validation 實例與目前被驗證的欄位会是有用的。

例如,在上述你可以这樣做:

public static function _validation_unique($val, $options)
{
	Validation::active()->set_message('unique', 'The field :label must be unique, but :value has already been used');
...
}