ikkez/f3-validation-engine

Cortex 和 PHP Fat-Free 框架的验证引擎

v1.7.3 2023-01-23 22:06 UTC

This package is auto-updated.

Last update: 2024-08-24 03:10:36 UTC


README

这是为 PHP Fat-Free 框架 提供的一个扩展,它提供了一种验证系统,特别适用于验证 Cortex 模型。验证系统基于知名的 GUMP 验证器,当然还有一些额外的功能

  • 基于 GUMP 的验证器
  • 多级验证
  • $fieldConf 中定义 Cortex 验证
  • 嵌套数组和依赖验证
  • 预验证和后验证过滤器
  • 包含 F3 兼容的语言字典
  • 基于字段的上下文语言覆盖
  • 也可在没有 Cortex 的情况下使用
  • 可扩展

目录

  1. 安装
  2. 入门
  3. 验证
    1. Cortex 映射器验证
    2. 数据数组验证
  4. 规则
    1. 验证器
    2. 过滤器
    3. 验证依赖
    4. 验证级别
    5. 数组验证
    6. 包含检查
  5. 错误处理
    1. 错误上下文
    2. 字段名称
    3. 前端集成
    4. 自定义错误
  6. 扩展
  7. 许可证

安装

使用 composer 安装,只需运行 composer require ikkez/f3-validation-engine。如果您不使用 composer,请将 src/ 文件夹添加到您的 AUTOLOAD 路径中,并单独安装 Wixel/GUMP

入门

默认情况下,验证引擎是静默的。为了利用验证过程中找到的错误,您需要将一些东西连接起来。这是在 onError 处理器中完成的,在那里您定义如何处理错误。一个示例

$validation = \Validation::instance();

$validation->onError(function($text,$key) {
	\Base::instance()->set('error.'.$key, $text);
	\Flash::instance()->addMessage($text,'danger');
});

在上面的示例中,我们注册了一个 onError 处理器,该处理器将错误键设置在 Hive 中,并添加了一条闪存消息到用户会话中。您可以随意全局定义此内容或动态更改 onError 处理器。

为了使错误文本正确显示,您需要加载包含的语言字典。为此,您可以添加 lang 文件夹到您的字典路径,如下所示

LOCALES = app/your/lang/,vendor/ikkez/f3-validation-engine/src/lang,vendor/ikkez/f3-validation-engine/src/lang/ext,

或者您也可以为这个调用一个小助手

\Validation::instance()->loadLang();

这使用了一种优化的加载方法,并且当您将 $ttl 作为第一个参数时,还包括了一些缓存技术。

注意:类似于 \Validation::instance()->loadLang(3600*24); 的缓存需要最新的 F3 边缘版本,否则可能会导致奇怪的词汇问题。至少使用

"bcosca/fatfree-core": "dev-master#b3bc18060f29db864e00bd01b25c99126ecef3d6 as 3.6.6"

验证

要使用验证引擎,您可以选择使用简单数组验证或使用具有预定义字段配置规则的 cortex 映射器。

Cortex 映射器验证

要使用映射器验证,您必须在 $fieldConf 数组中定义验证规则。这可以看起来像这样

protected $fieldConf = [
	'username' => [
		'type' => Schema::DT_VARCHAR128,
		'filter' => 'trim',
		'validate' => 'required|min_len,10|max_len,128|unique',
	],
	'email' => [
		'type' => Schema::DT_VARCHAR256,
		'filter' => 'trim',
		'validate' => 'required|valid_email|email_host',
	],
];

要开始验证,您可以使用此方法

$valid = $validation->validateCortexMapper($mapper);

或者将适当的验证特性添加到您的模型类中

namespace Model;
class User extends \DB\Cortex {

	use \Validation\Traits\CortexTrait;
	
	// ...
} 

然后直接在您的模型上调用 $mapper->validate();

数据数组验证

如果您只有一个简单数组,并想对某些规则进行验证,您也可以这样做

$data = [
  'username' => 'Jonny',
  'email' => 'john.doe@domain.com',
];
$rules = [
  'username' => [
    'filter' => 'trim',
    'validate' => 'required|min_len,10|max_len,128|unique',
  ],
  'email' => [
    'filter' => 'trim',
    'validate' => 'required|valid_email|email_host',
  ]
];
$valid = $validation->validate($rules, $data);

验证方法总是返回一个布尔值,以指示数据是否有效(TRUE)或是否找到任何错误(FALSE);

规则

验证器

GUMP的默认验证器包括:

  • required
    确保指定的键值存在且不为空
  • valid_email
    检查是否为有效的电子邮件地址
  • max_len,n
    检查键值长度,确保其长度不超过指定的长度。n = 长度参数。
  • min_len,n
    检查键值长度,确保其长度不短于指定的长度。n = 长度参数。
  • exact_len,n
    确保键值长度精确匹配指定的长度。n = 长度参数。
  • alpha
    确保键值中只包含字母字符(a-z, A-Z)
  • alpha_numeric
    确保键值中只包含字母数字字符(a-z, A-Z, 0-9)
  • alpha_dash
    确保键值中只包含字母数字字符、破折号和下划线(a-z, A-Z, 0-9, _-)
  • alpha_space
    确保键值中只包含字母数字字符和空格(a-z, A-Z, 0-9, \s)
  • numeric
    确保只有数字键值
  • integer
    确保只有整数键值
  • boolean
    检查是否为PHP接受的布尔值,对 "1"、"true"、"on" 和 "yes" 返回 TRUE
  • float
    检查是否为浮点值
  • valid_url
    检查是否为有效的URL或子域
  • url_exists
    检查URL是否存在并可访问
  • valid_ip
    检查是否为有效的通用IP地址
  • valid_ipv4
    检查是否为有效的IPv4地址
  • valid_ipv6
    检查是否为有效的IPv4地址
  • guidv4
    检查是否为有效的GUID(v4)
  • valid_cc
    检查是否为有效的信用卡号码(使用MOD10校验算法)
  • valid_name
    检查是否为有效的人类姓名格式
  • contains,n
    验证值是否包含在预定义的值集中
  • contains_list,n
    验证值是否包含在预定义的值集中。有效的值列表必须以分号分隔的格式提供(例如:value1;value2;value3;..;valuen)。如果发生验证错误,则不会显示有效的值列表(这意味着,错误将只说明输入无效,但不会向用户显示有效集)。
  • doesnt_contain_list,n
    验证值是否不包含在预定义的值集中。分号 (;) 分隔,列表不输出。更多信息请参见上述规则。
  • street_address
    检查提供的字符串是否是可能的街道地址。1个数字,1个或多个空格,1个或多个字母
  • date
    确定提供的输入是否为有效的日期(ISO 8601)
  • min_numeric
    确定提供的数值是否高于或等于特定值
  • max_numeric
    确定提供的数值是否低于或等于特定值
  • min_age,n
    确保字段包含具有最小年龄的日期,例如 min_age,18。输入日期需要与ISO 8601 / strtotime 兼容。
  • starts,n
    确保值以特定的字符/字符集开头
  • equalsfield,n
    确保提供的字段值等于当前字段值。
  • iban
    检查是否为有效的IBAN
  • phone_number
    验证与以下示例匹配的电话号码:555-555-5555 , 5555425555, 555 555 5555, 1(519) 555-4444, 1 (519) 555-4422, 1-555-555-5555
  • regex
    您可以使用以下格式传递自定义正则表达式:'regex,/your-regex/'
  • valid_json_string
    验证字符串是否为有效的JSON格式

其他验证器

  • empty
    检查字段值是否为 empty
  • notempty
    确保字段值不为 empty,不是空字符串,也不是字符串 "0"
  • notnull
    确保字段值不是 NULL。这是一个较宽松的“必填”检查。
  • email_host
    检查给定电子邮件地址的MX域名记录。如果主机系统不接受电子邮件,则失败。此验证器仅对有效电子邮件起作用,但不会验证电子邮件地址本身(与valid_email结合使用)。
  • unique - Cortex仅支持 -
    检查给定的字段值在数据库表中是否唯一(例如用户名)。

过滤器

可以在验证之前使用过滤器来净化输入数据。基本上,过滤器是一个简单的PHP函数,返回一个字符串。

您可以设置在验证之前应用的常规filter和在之后应用的post_filter

'foo' => [
	'filter' => 'trim|base64_decode',
	'validate' => 'required|valid_url',
	'post_filter' => 'base64_encode',
],

默认GUMP过滤器

  • sanitize_string
    移除脚本标签并编码HTML实体,类似于GUMP::xss_clean();
  • urlencode
    编码URL实体
  • htmlencode
    编码HTML实体
  • sanitize_email
    从电子邮件地址中移除非法字符
  • sanitize_numbers
    移除任何非数字字符
  • sanitize_floats
    移除任何非浮点字符
  • trim
    从字符串的起始和结束处移除空格
  • base64_encode
    对输入进行Base64编码
  • base64_decode
    对输入进行Base64解码
  • sha1
    使用安全的sha1算法对输入进行加密
  • md5
    对输入进行MD5编码
  • noise_words
    从字符串中移除噪音单词
  • json_encode
    创建输入的JSON表示
  • json_decode
    解码JSON字符串
  • rmpunctuation
    从字符串中移除所有已知标点符号字符
  • basic_tags
    从文本中移除所有布局导向的HTML标签,仅留下基本标签
  • whole_number
    确保提供的数值以整数形式表示
  • ms_word_characters
    将MS Word特殊字符[“”‘’–…]转换为Web安全字符
  • lower_case
    转换为小写
  • upper_case
    转换为大写
  • slug
    创建Web安全的URL别名

其他过滤器

  • website
    如果未指定协议,则将http://协议添加到URI前面。

验证依赖

您可以选择跳过一条验证规则,并在满足另一个字段的特定条件时才考虑它。

在下面的示例中,当bar = 2时,foo才需要。

'foo' => [
	'validate' => 'required',
	'validate_depends' => [
		'bar' => 2
	]
]

您还可以使用一些更高级的依赖性检查,如嵌套验证规则。

'foo' => [
	'validate' => 'required',
	'validate_depends' => [
		'bar' => ['validate', 'min_numeric,2']
	]
]

当嵌套验证为TRUE(有效)时,则满足依赖性,并且foo的验证继续进行,否则将跳过。如果这还不够,您还可以添加一个自定义函数。

'validate_depends' => [
	'bar' => ['call', function($value,$input) { return (bool) $value % 3 }]
]

一个类似F3的调用字符串,如['call', 'Foo->bar']也是可能的。

验证级别

类似于验证依赖性,您还可以定义验证级别。如果字段上定义了验证级别,则其验证将完全跳过(但是应用过滤器)。

验证级别在您希望在某些步骤中验证记录时很有用,例如,“草稿”在发布之前可能需要较少的验证规则。

您可以像这样定义验证级别

'foo' => [
	'validate_level'=>2,
	'validate' => 'required',
]

默认情况下,所有验证都使用level = 0。要触发此验证规则,您需要调用带有新$level的validate函数。

$validation->validateCortexMapper($mapper, $level);
// OR
$validation->validate($rules, $data, $level);

级别检查的默认比较操作符为<=。因此,级别-2的验证也会触发级别0和级别1的验证规则。如果您只想检查级别-2,还可以设置新的$level_op参数。

数组验证

如果您在数据或模型中有一个数组字段,您还可以验证某些数组键。

'contact' => [
	'type' => self::DT_JSON,
	'validate_array' => [
		'name' => ['validate'=>'required'],
		'address' => ['validate'=>'required|street_address'],
		'region' => ['validate'=>'required'],
		'zip' => ['validate'=>'required'],
	]
]

嵌套数组

还可以验证嵌套数组/关联数组数组。

'partners' => [
	'type' => self::DT_JSON,
	'validate_nested_array' => [
		'name' => ['validate'=>'required'],
		'profession' => ['validate'=>'required'],
		'phone' => ['validate'=>'required'],
		'image' => ['filter'=>'upload'],
	]
]

包含检查

- 正在开发中 -

还可以通过在$fieldConf(或$rules数组)中的item键中简单定义,来定义contains将检查的值(contains验证器)。

'foo' => [
	'type' => Schema::DT_VARCHAR128,
	'item' => [
		'one',
		'two',
		'three',
	]
]

如果值与定义的项目之一不匹配,验证将失败。也可以将一个字符串放入item,它是一个包含项目的强F3 hive键

错误处理

错误信息是从字典文件加载到F3 hive中的。

默认的hive位置在:{PREFIX}error.validation.{type}

这意味着,如果你的PREFIXll.,那么required验证器的默认文本在ll.error.validation.required。当然,你也可以在项目的自定义语言文件中覆盖它,但有时你可能只想为模型中的一个字段更改它。这里我们可以使用错误上下文

错误上下文

当你验证Cortex模型时,它将自动根据类命名空间有一个上下文。所以当你验证\Model\User时,错误上下文是error.model.user

要覆盖默认的错误消息,针对一个特定字段和一个特定验证器,可以在这个上下文中创建一个新的语言键。

[error.model.user]
username.required = You Shall Not Pass!
username.unique = Doh! It's already taken.

字段名称

大多数错误消息包含一个字段标识符/字段名称,错误属于该字段。默认情况下,此名称由该字段的数组键构建,但这通常不够。为了在错误消息中也有适当的翻译字段名称,系统会根据模型上下文和字段查找语言键。

例如,用户模型中的用户名字段应该标记为

model.user.username.label = 昵称

在此过程中,你也可以考虑占位符标签、帮助文本等,这些都可能适合此架构,并可能改善前端连接。

当你使用validate_arrayvalidate_nested_array规则验证数组时,字段标签会移动到条目字段下方的键。例如,当你有一个包含邮编字段的用户模型中的数组地址字段时,标签上下文将是

model.user.address.zip.label = 邮编

默认字段标签

如果你有多个模型上常见的字段,并且不想为每个模型重复定义这些翻译标签,你可以在model.base中定义一个默认回退标签。

[model.base]
deleted_at.label = deleted at
enabled_from.label = visible from
enabled_until.label = visible until

自定义模型上下文名称转换

默认情况下,模型名称被转换为小写字符串。即此类\Model\BackendUser被转换为上下文:model.backenduser。你可以通过设置一个自定义函数来调整此行为。

\Validation::instance()->setStringifyModel(function($mapper) {
	return implode('.',array_map('lcfirst',explode('\\',get_class($mapper))));
});

此示例将类名转换为model.backendUser

前端集成

在设置错误键的onError处理程序中,例如从样本开始,你可以轻松地使用它们来显示自定义错误消息或向标记添加类。

<div class="uk-card uk-card-default {{ @@error.model.user.username ? 'frame-red' : 'frame-grey' }}">
  <div class="uk-card-body">
    <h3 class="uk-card-title">{{ @ll.model.user.username.label }}</h3>
    <div class="uk-margin">
      <input class="uk-input {{ @@error.model.user.username ? 'uk-form-danger' : '' }}" 
        type="text" name="username" placeholder="{{ @@ll.model.user.username.placeholder }}">
    </div>
  </div>
</div>

如果你喜欢,你也可以根据失败的验证器添加自定义的帮助文本。

例如,添加一个<F3:check if="{{@@error.model.user.username.unique}}">或为必填验证器添加不同的一个,你可以构建复杂和功能性的表单状态。有关附加的闪存消息,请参阅f3-flash

自定义错误

如果你想只设置自定义错误消息,请阅读上面的错误上下文

如果你需要手动触发错误,因为有些验证部分目前超出了范围,你可以自己进行验证并自行发出错误,如下所示

$valid = $userModel->validate();

if (!$userModel->foo1 && !$userModel->foo2) {
  \Validation::instance()->emitError('foo','required','model.user.foo');
  $valid = false;
}
if ($valid) {
  // continue
}

emitError(字符串 $field, 字符串 $type, 字符串 | 数组 $context = NULL, 字符串 $fallback = NULL)

要从不同的字段使用错误消息,你可以使用数组作为$context参数。

\Validation::instance()->emitError('phone_mail_copy','required',[
	'model.employerprofile.phone_mail_copy', // context
	'model.employerprofile.phone_mail_orig', // context label
]);

你还可以在自定义错误中使用参数。

if ($f3->get('POST.password') !== $f3->get('POST.password2')) {
	// The {0} field does not equal {1} field
	\Validation::instance()->emitError(['password','Password repeat'],'equalsfield','model.user');
}

扩展

扩展系统很简单。要添加一个新的验证器

\Validation::instance()->addValidator('is_one', function($field, $input, $param=NULL) {
	return $input[$field] === 1;
}, 'The field "{0}" must be 1');

也要在error.validation.is_one中添加新的翻译键,否则只会显示回退文本,或者当没有提供文本时显示上下文。

并且添加一个新的 过滤器

\Validation::instance()->addFilter('nl2br',function($value,$params=NULL) {
	return nl2br($value);
});

您也可以使用 F3 调用字符串

$validator = \Validation::instance(); 
$validator->addValidator('is_one','App\MyValidators->is_one');
$validator->addFilter('nl2br','App\MyFilters->nl2br');

许可证

GPLv3