inpsyde/validator

Inpsyde Validator 库。

1.3.0 2023-05-17 13:40 UTC

This package is auto-updated.

Last update: 2024-09-05 14:06:13 UTC


README

本软件包提供了一组用于 WordPress 的验证器。

内容

安装

最佳通过 Packagist 的 Composer 提供。软件包名称为 inpsyde/validator

是什么以及它的工作原理

该软件包提供验证器对象,可用于验证某些给定的数据是否满足特定要求。

每个验证器的最重要方法是 is_valid(),它接收一些数据并返回 truefalse,具体取决于提供的数据是否满足验证器要求。

我们可以区分三种类型的验证器

  • "简单"
  • "二级"
  • "复合"

简单验证器用于验证单个值,根据某些规范。

二级验证器通过修改简单验证器的行为来创建。可以将其视为验证器的"装饰器"。

复合验证器是通过组合多个验证器来创建的。

简单验证器

以下是对当前提供的简单验证器的总结

所有验证器都在 Inpsyde\Validator 命名空间中定义,因此可以使用如下方式使用它们

$value = 8;

$between = new Inpsyde\Validator\Between(['min' => 10, 'max' => 20, 'inclusive' => false]);

if ( $between->is_valid($value) ) {
  echo "Value {$value} is between 10 and 20".
} else {
  echo "Value {$value} is not between 10 and 20".
}

其他验证器可以以类似的方式使用。

二级验证器

目前,可用的以下二级验证器

所有二级验证器都有一个 with_validator() 静态方法,可以用作命名构造函数来获取实例。

Negate 示例

以下是一个如何使用 Negate 来检查给定的值是否不包含在给定的值堆中的示例

$not_in_array = Negate::with_validator( new InArray( [ 'haystack' => [ 'foo', 'bar' ] ] ) );

$not_in_array->is_valid( 'hello' ); // true
$not_in_array->is_valid( 'foo' ); // false

Bulk 示例

以下是一个如何使用 Bulk 来检查给定的数组是否只包含字符串的示例

$array_of_strings = Bulk::with_validator( new Type( [ 'type' => 'string' ] ) );

$array_of_strings->is_valid( [ 'foo', 'bar' ] ); // true
$array_of_strings->is_valid( [ 'foo', true  ); // false

Pool 示例

以下是一个如何使用 Pool 来检查给定的数组是否至少包含一个 WP_Post 对象的示例

$has_post = Pool::with_validator( new Type( [ 'type' => 'WP_Post' ] ) );

$has_post->is_valid( [ 'foo', new \WP_Post([ 'id' => 1 ]) ] ); // true
$has_post->is_valid( [ 'foo', true  ); // false

Pool 遍历给定的值,并在值的第一项验证内部验证器时返回 true。

复合验证器

目前,以下复合验证器可用

DataValidator 是本软件包中最强大的验证器,因为它是实现 ErrorLoggerAwareValidatorInterface 接口的唯一验证器,这使得以非常简单的方式获取验证数据的错误消息成为可能。因此,以下单独介绍了此验证器的使用。

Multi 示例

以下是一个如何使用 Multi 验证器来检查给定的值是否是数组、并且具有两个项目、并且这两个项目都是字符串的示例

use Inpsyde\Validator;

$two_items_string_array = new Validator\Multi(
	['stop_on_failure' => TRUE ],
	[
		new Validator\Type( [ 'type' => 'array' ] ),
		new Validator\Size( [ 'type' => 2 ] ),
		Validator\Bulk::with_validator( new Validator\Type( [ 'type' => 'string' ] ) ),
	]
);

$two_items_string_array->is_valid( [' foo', 'bar' ] ); // true
$two_items_string_array->is_valid( [ 'foo', 1 ] ); // false
$two_items_string_array->is_valid( [ 'foo', 'bar', 'baz' ] ); // false

第一个构造函数参数是一个选项数组,就像所有“简单”验证器一样。第二个参数是一个验证器数组。

请注意我们如何使用一个次要验证器(Bulk)作为Multi子验证器:这是完全可以的,因为简单、次要和复合验证器都实现了相同的接口。

默认情况下,当调用is_valid()时,所有验证器都会执行给定的值,但是将选项stop_on_failure设置为TRUE,验证器将在遇到第一个失败的验证器时停止执行验证。

构建Multi验证器实例的另一种(且不那么啰嗦)方法是使用接受可变数量验证器对象的静态方法with_validators()

use Inpsyde\Validator;

$two_items_string_array = Validator\Multi::with_validators(
	new Validator\Type( [ 'type' => 'array' ] ),
    new Validator\Size( [ 'type' => 2 ] ),
    Validator\Bulk::with_validator( new Validator\Type( [ 'type' => 'string' ] ) ),
);

这样构建时,stop_on_failure选项将设置为默认值,即false,但可以通过调用获取的实例上的stop_on_failure()方法将其设置为true

use Inpsyde\Validator;

$two_items_string_array = Validator\Multi::with_validators(...$validators)->stop_on_failure();

MultiOr 示例

MultiOrMulti非常相似,但后者使用AND运算符组合验证器,前者使用OR运算符。

换句话说,使用Multi时,所有内部验证器都必须通过验证,才能使Multi通过验证;而MultiOr只要至少有一个内部验证器通过验证,就会通过验证。

以下是一个如何使用MultiOr来验证一个值是否在5到10之间或50到100之间的示例。

use Inpsyde\Validator;

$custom_range = Validator\MultiOr::with_validators(
	new Validator\Between( [ 'min' => 5, 'max' => 10 ] ),
    new Validator\Between( [ 'min' => 50, 'max' => 100 ] ),
);

$custom_range->is_valid( 7 ) // true
$custom_range->is_valid( 30 ) // false
$custom_range->is_valid( 60 ) // true

错误代码和输入数据

一些验证器可能会由于不同的原因而失败。

例如,RegEx验证器可能会因为提供的输入不是字符串,或者因为模式无效,或者因为给定值与提供的模式不匹配而失败。

这就是为什么所有验证器都附带两个额外的方法(除了is_valid()之外)的原因。

  • get_error_code()
  • get_input_data()

get_error_code()返回一个代码,用于识别导致验证器失败的错误类型。

所有默认错误代码都是Inpsyde\Validator\Error\ErrorLoggerInterface接口的常量。

例如,如果inclusive选项为true,则Between验证器可能会返回ErrorLoggerInterface::NOT_BETWEEN_STRICT,如果它为false,则返回ErrorLoggerInterface::NOT_BETWEEN

get_input_data()返回一个数组,包含以下信息:

  • 验证器选项
  • 经过验证的值

例如,在上面的例子中,Validator\Between::get_input_data()可能会返回

[
	'min'   => 10,
	'max'   => 20,
	'value' => 8,
]

验证器工厂

该软件包附带一个验证器工厂类,可以从一些配置值开始构建验证器实例。

当需要从配置文件批量构建多个验证器,或者需要进行延迟实例化时,这非常有用。

该工厂只有一个方法create(),它接受一个验证器标识符(作为字符串)和可选的选项数组。

使用示例

$configuration = [
	'between'   => [ 'min' => 10, 'max' => 20 ],
	'not-empty' => [],
	'in_array'  => [ 'haystack' => [ 'a', 'b', 'c' ] ]
];

$factory = new Inpsyde\Validator\ValidatorFactory();

$validators = [];

foreach($configuration as $identifier => $options) {

	$validators[] = $factory->create( $identifier, $options);
}

为了构建提供的验证器,还可以使用不包含命名空间的类名作为标识符。

$configuration = [
	'Between'  => [ 'min' => 10, 'max' => 20 ],
	'NotEmpty' => [],
	'InArray'  => [ 'haystack' => [ 'a', 'b', 'c' ] ]
];

对于任何实现验证器接口的自定义验证器(见下文),可以传递类的完全限定名以获取构建的实例。

错误消息

此软件包附带一些对象,当验证器失败时,它们可以获取错误消息。

它们是

  • Inpsyde\Validator\Error\ErrorLogger
  • Inpsyde\Validator\Error\WordPressErrorLogger

这两个记录器以相同的方式工作,但是WordPressErrorLogger支持通过WordPress翻译功能进行翻译。

使用这些对象显示错误涉及两个步骤:

  1. 记录错误(s)
  2. 获取记录的错误数组

代码看起来像这样

use Inpsyde\Validator;

$between = new Validator\Between([ 'min' => 10, 'max' => 20, 'inclusive' => false ]);

if ( ! $between->is_valid() ) {

	$logger = new Validator\Error\WordPressErrorLogger();
	$logger->log_error( $between->get_error_code(), $between->get_input_data() );
	
	foreach( $logger->get_error_messages() as $error ) {
		echo "<p>{$error}</p>";
	}
}

它可能看起来需要做很多工作,但是当使用DataValidator(见下文)验证数据时,上述大部分代码都是不必要的。

错误模板

当使用错误记录器时,错误消息使用“模板”创建:包含占位符的字符串消息。

每个作为ErrorLoggerInterface常量的错误代码都有一个相关的模板。

例如,对于代码ErrorLoggerInterface::NOT_BETWEEN,相关的模板是

'The input <code>%value%</code> is not between <code>%min%</code> and <code>%max%</code>, inclusively.'

其中,%value%%min%%max% 是占位符,在记录错误时,将由 get_input_data() 传递的数据替换。

错误模板可以通过两种方式自定义

  1. 替换记录器中用于特定代码的模板
  2. 在记录错误时传递特定的模板

特定于代码的模板

错误记录器提供了一个名为 use_error_template() 的方法,可以用来为给定的错误代码设置自定义的错误模板。

例如

use Inpsyde\Validator\Error;

$logger = new Error\WordPressErrorLogger();
$logger->use_error_template( Error\ErrorLoggerInterface::NOT_BETWEEN, 'Hey, the value %value% is not ok.' );

这样做,所有 Error\ErrorLoggerInterface::NOT_BETWEEN 的错误都将使用给定的模板,除非在记录错误时提供了特定的错误代码模板。

不是使用 use_error_template() 逐个替换错误模板,而是可以通过将模板数组传递给记录器构造函数来一次性替换更多模板,其中数组的键是错误代码

use Inpsyde\Validator\Error;

$custom_templates = [
	Error\ErrorLoggerInterface::NOT_BETWEEN        => 'Hey, the value %value% is not ok.',
	Error\ErrorLoggerInterface::NOT_BETWEEN_STRICT => 'Hey, the value %value% is not ok. Really.' 
];

$logger = new Error\WordPressErrorLogger( $custom_templates );

特定于错误的模板

log_error() 方法接受第三个参数,用于传递仅针对该错误使用的特定模板

use Inpsyde\Validator\Error;

$logger = new Error\WordPressErrorLogger();

$logger->log_error(
	$validator->get_error_code(),   // code
	$validator->get_input_data(),   // input data
	'%value% is wrong, try again.', // custom error message template
);

当这样使用时,自定义模板不会影响相同代码的其他消息,而只会影响正在记录的错误。

DataValidator

DataValidator 是该包中功能更强大的验证器。除了收集更多的验证器外,它还提供了比其他验证器更多的方法,包括 get_error_messages(),它返回在验证给定的数据时发生的所有错误的数组。

添加到 DataValidator 的 "Child" 验证器可以用来验证

  • 所有 要验证的数据项
  • 特定的 通过其 "key" 识别的数据项

向所有项目添加验证器

DataValidator 有两种方法可以向要验证的所有数据项添加验证器,它们是

  • add_validator()
  • add_validator_with_message()

第一个只接受验证器实例,第二个还接受自定义的消息模板,当此验证器失败时将用于构建错误消息。

示例

use Inpsyde\Validator;

$validator = new Validator\DataValidator();

$validator
	->add_validator_with_message( new Validator\NotEmpty(), 'The given value must not be empty.' )
	->add_validator( new Validator\Url([ 'check_dns' => true ]) );
	
$validator->is_valid([
	'http://www.example.com',
	'http://example.com',
	'this-will-fail'
]);

传递给 is_valid() 的数组中的每个元素都将与添加的验证器进行验证。

在上面的示例中,请注意,add_validator_with_message()add_validator 都实现了 "流畅接口",允许通过返回验证器实例的方式 "链式" 调用它们。

向特定项目添加验证器

DataValidator 还有一个方法,允许向给定数据的特定元素添加验证器,即 add_validator_by_key()

它接受三个参数:验证器实例、用于标识数据元素的键,以及可选的错误消息模板,用于验证器。

示例

use Inpsyde\Validator;

$validator = new Validator\DataValidator();

$validator
	->add_validator_by_key( new Validator\NotEmpty(), 'name', 'Name cannot be empty.' )
	->add_validator_by_key( new Validator\Url(), 'homepage', 'Homepage must be a valid URL.' )
	
$valid = $validator->is_valid([
	'name'     => 'Inpsyde',
	'homepage' => 'http://www.inpsyde.com',
]);

if (! $valid) {
	foreach( $validator->get_error_messages() as $error ) {
		echo "<p>{$error}</p>";
    }
}

DataValidator 是唯一支持 get_error_messages() 的验证器,可以获取所有发生的错误数组。

自定义错误消息模板

通过使用 add_validator_by_key()add_validator_with_message(),可以在验证器级别自定义错误模板,但是,DataValidator 构造函数可选地接受一个错误记录器实例,该实例将用于构建所有消息。

因此,可以创建一个带有自定义错误消息的错误记录器实例(如上所示),并将其传递给 DataValidator 构造函数

use Inpsyde\Validator\Error;
use Inpsyde\Validator\DataValidator;

$custom_templates = [
	Error\ErrorLoggerInterface::NOT_BETWEEN        => 'Hey, the value %value% is not ok.',
	Error\ErrorLoggerInterface::NOT_BETWEEN_STRICT => 'Hey, the value %value% is not ok. Really.' 
];

$logger = new Error\WordPressErrorLogger( $custom_templates );

$validator = new DataValidator( $logger );

错误消息中的项目键

使用 DataValidator 时,还有一个额外的占位符:'%key%',它将被替换为导致错误的值的项目键。

默认情况下,错误消息没有 '%key%' 占位符,因此字符串 "<code>%key%</code>: " 将被添加到默认消息前。

例如,默认消息模板

输入 %value% 不是一个有效的 URL。

变为

%key%:输入 %value% 不是一个有效的 URL。

这仅发生在未使用 add_validator_by_key()add_validator_with_message() 提供的特定自定义错误模板时,当提供自定义错误模板时,不会在其前添加任何内容,但如果自定义模板包含 '%key%' 占位符,它也将被替换。

错误消息中的项目键标签

有时可能希望错误信息不包含项目键,而是标签。

例如,如果验证器用于验证来自HTML表单的数据,则错误信息包含输入标签而不是输入名称将很理想。

然而,输入名称(将在提交的数据数组中作为键)也是必需的,以便让DataValidator识别每个字段应用哪个验证器。

因此,add_validator_by_key()add_validator_with_message()都支持第二个参数$key的特殊语法:一个包含两个元素的数组,键为'key''label'

示例

use Inpsyde\Validator;

$validator = new DataValidator();

$validator->add_validator_by_key(
	new Validator\NotEmpty(),
	[ 'key' => 'username', 'label' => __( 'User name', , 'txtdomain' ) ], // key param is an array here
	sprintf( __( '%s must not be empty.', 'txtdomain' ), %key% )
);

if ( ! $validator->is_valid( [ 'username' => '' ] ) ) {
	$messages = $validator->get_error_messages();
}

在上面的例子中,由于username键的值为空,构建的错误信息将是以下翻译版本

用户名不能为空。

注意标签是如何用来替代键而不是占位符。

自定义验证器

可以创建自定义验证器与包一起使用。

自定义验证器应实现接口ExtendedValidatorInterface,其中包含以下方法:

  • get_error_code()
  • get_input_data()
  • get_error_messages()(已弃用)
  • is_valid()

该包提供了2个特例,可以用于实现前3个方法,只留下is_valid()由实现者实现。

特别考虑GetErrorMessagesTrait,它包含已弃用的get_error_messages()的实现(有关更多信息,请参见下文的"从版本1.0升级")。

自定义验证器示例

一个简单的自定义验证器可能如下所示:

namespace MyPlugin\Validator;

use Inpsyde\Validator\ExtendedValidatorInterface;
use Inpsyde\Validator\GetErrorMessagesTrait;
use Inpsyde\Validator\ValidatorDataGetterTrait;
use Inpsyde\Validator\Error\ErrorLoggerInterface;

class YesNo implements ExtendedValidatorInterface {

	const ERROR_CODE = 'not_yes_no';

	use GetErrorMessagesTrait;
	use ValidatorDataGetterTrait;
	
	public function is_valid( $value ) {
	
		/** @see ValidatorDataGetterTrait */
		$this->input_data[ 'value' => $value ]; 
		
		if ( ! is_string( $value ) ) {
			// this is a default error
			$this->error_code = ErrorLoggerInterface::INVALID_TYPE_NON_STRING;
			
			return false;
		}
			
		if ( ! in_array( strtolower( $value ), [ 'yes', 'no' ], true ) ) {
		    // custom error
			$this->error_code = self::ERROR_CODE;
			
			return false;
		}
		
		return true;
	}
 
}

验证器在错误情况下可能发出两个错误代码,其中一个为默认错误代码,另一个为自定义错误代码。

如果验证器打算与DataValidator一起使用,则需要将自定义代码添加到错误记录器中,如下所示:

namespace MyPlugin;

use Inpsyde\Validator\DataValidator;
use Inpsyde\Validator\Error\WordPressErrorLogger;

$yes_no_message = sprintf(
	__( 'Accepted values are only "yes" and "no". "%s" was given.', 'txtdmn' ),
	'%value%'
);

$logger = new WordPressErrorLogger([ Validator\YesNo::ERROR_CODE => $message ]);

$validator = new DataValidator( $logger );

$validator->add_validator_by_key( new Validator\YesNo(), 'accepted' );

从版本 1.0 升级

  • 接口ExtendedValidatorInterface扩展了ValidatorInterface并包含get_error_code()get_input_data(),该接口在包的版本1.1中引入。在版本1.0中,验证器仅实现了ValidatorInterface
  • get_error_messages()从版本1.1开始已弃用
  • ExtendedValidatorInterface存在的整个原因是与为版本1.0构建的任何自定义验证器保持向后兼容性,并扩展ValidatorInterface(我们无法在不破坏兼容性的情况下向其添加方法)。

由于上述原因,从版本2.0开始

  • get_error_messages()将被删除
  • get_error_code()get_input_data()将被添加到ValidatorInterface
  • 因此,ExtendedValidatorInterface将变为空,并仅扩展ValidatorInterface。它将为了与为1.1+编写的自定义验证器保持向后兼容性而维护,但将被弃用并在版本3.0中删除。

其他说明

错误、技术提示或贡献

请在GitHub仓库上给我们反馈,贡献并提交技术错误。

许可证

好消息,这个插件对每个人都是免费的!因为它是在MIT许可下发布的,您可以在您的个人或商业博客上免费使用它。

变更日志

请参阅提交记录或阅读简短版本