swoft2 教程系列-验证器

正常情况都需要对用户输入参数进行校验,此时就会用到验证器。验证器可以验证控制器中参数,也支持验证 Websocket 参数以及 RPC 参数验证,提供默认和自定义两种类型的验证器,还可添加自定义验证规则。

配置

需要启用验证器,这里以 Http-server 启用为例,其它一样(app/bean.php)

 

return [
 // ......
 'httpDispatcher' => [
 // ......
 'afterMiddlewares' => [
            \Swoft\Http\Server\Middleware\ValidatorMiddleware::class
 ]
 // ......
 ],
 // ......
]

 

说明 afterMiddlewares 与 middlewares 中间件 中间件的不同在于 afterMiddlewares 中间件 总是在 middlewares 中间件全部执行完后执行.

声明验证器简单示例

一个验证器由多个验证条件组合,建议验证器按数据库表进行组合,这样可以充分的重复利用验证器里面的组合条件。

<?php
namespace App\Http\MyValidator;

use Swoft\Validator\Annotation\Mapping\IsInt;
use Swoft\Validator\Annotation\Mapping\Max;
use Swoft\Validator\Annotation\Mapping\Min;
use Swoft\Validator\Annotation\Mapping\Validator;

/**
 * 商品验证
 * @Validator(name="orders")
 */
class OrderValidator{
 /**
     * @IsInt(message="用户ID不能为空")
     * @Min(value=1,message="用户ID不正确")
     * @var int
     */
 protected $user_id;

 /**
     * @IsInt(message="订单状态不能空")
     * @Min(value=0,message="状态不正确min")
     * @Max(value=5,message="状态不正确max")
     * @var int
     */
 protected $order_status;
 /**
     * @IsInt(message="订单金额不为空")
     * @Min(value=1,message="订单金额不正确")
     * @var int
     */
 protected $order_money;
}

代码解析

注解

@Validator 声明该类是一个验证器,推荐给验证器命名,这里我们给验证器命名为 orders

验证项

验证项是组成验证器的唯一条件,标记有类型注解的属性就是一个验证项,一个验证器可以有多个验证项。

  1. 属性的默认值就是参数的默认值,如果属性没有定义默认值,代表参数没有定义默认值且必须传递。
  2. 一个属性必须定义一个类型注解,否则不是一个验证项且对参数验证无效。
  3. 一个属性可以多个条件注解,按照定义顺序验证数据。
  4. 默认属性名称就是需要验证的参数名称,也可以通过类型注解的 name 参数映射需要验证的字段名称。
  5. 若验证不通过时,将会抛出 Swoft\Validator\Exception\ValidatorException 异常。

验证器使用

1 注解使用

<?php
namespace App\Http\Controller;
use App\Models\KfMain;
use Swoft\Http\Server\Annotation\Mapping\Controller;
use Swoft\Http\Server\Annotation\Mapping\RequestMapping;
use Swoft\Http\Server\Annotation\Mapping\RequestMethod;
use Swoft\Validator\Annotation\Mapping\Validate;

/**
 * Class Order
 * @Controller(prefix="/order")
 */
class Order{
 /**
     * @Validate(validator="orders")
     * @RequestMapping(route="new",method={RequestMethod::POST})
     */
 public function  createOrder(){

         $req=Swoft\Context\Context::mustGet()->getRequest();

           $raw = $req->getBody()->getContents();

           $data = json_decode($raw, true);// key=>value数组

 return $ordersPost;
 }
}

 

说明 只需要使用 Validate 注解并指定验证器名称,就能自动验证数据.默认情况是验证 post 数据,如果需要验证 get 数据  @Validate(validator="orders",type="get")  设置type参数为 get 即可
  1. 非注解使用

全局方法 不推荐使用

function validate(array $data, string $validatorName, array $fields = [], array $userValidators = []): array

 

全局函数使用,当验证器失败会抛出 Swoft\Validator\Exception\ValidatorException 异常

参数说明:

  1. $data 需要验证的数据,必须是数组 KV 格式
  2. $validatorName 使用的验证器( @Validator() 注解标记的 )
  3. $fields 需要验证的字段,为空验证器所有字段
  4. $userValidators 同时使用的自定义验证器,支持两种格式。

常用验证规则

@IsArray

验证规则:

验证参数值必须是数组,使用 is_array()函数进行校验。

参数说明:

  • name: 映射需要验证的字段名称,默认属性名称。
  • message: 验证失败时的错误提示,若不设置则默认使用框架内置的。
  • 使用示例: @IsArray(name="field", message="error message")

@IsBool

验证规则:

验证参数值必须是 bool 类型,注意字符串 true false ,会验证成 bool 类型,其余数据将会使用is_bool()函数进行验证。

参数说明:

  • name: 映射需要验证的字段名称,默认属性名称。
  • message: 验证失败时的错误提示,若不设置则默认使用框架内置的。
  • 使用示例:@IsBool(name="field", message="error message")

@IsFloat

验证规则:

验证参数值必须是浮点数,使用filter_var()函数进行验证。

参数说明:

  • name: 映射需要验证的字段名称,默认属性名称。
  • message: 验证失败时的错误提示,若不设置则默认使用框架内置的。
  • 使用示例:@IsFloat(name="field", message="error message")

@IsInt

验证规则:

验证参数值必须是整数,使用filter_var()函数进行验证。

参数说明:

  • name: 映射需要验证的字段名称,默认属性名称。
  • message: 验证失败时的错误提示,若不设置则默认使用框架内置的。
  • 使用示例: @IsInt(name="field", message="error message")

@IsString

验证规则:

验证参数值必须是字符串,使用is_string()函数进行验证。

参数说明:

  • name: 映射需要验证的字段名称,默认属性名称。
  • message: 验证失败时的错误提示,若不设置则默认使用框架内置的。
  • 使用示例:@IsString(name="field", message="error message")

条件注解

  • 一个属性可以多个条件注解,按照定义顺序验证数据。

@AfterDate

验证规则:

验证参数值必须在某个日期之后,参数支持 字符串时间戳、格式化日期字符串(只支持 Y-m-d H:i:s)、整型时间戳,可在@IsString 或 @IsInt 类型注解中使用。

参数说明:

  • date: 要对比的日期值,只能是 Y-m-d H:i:s 格式。
  • message: 验证失败时的错误提示,若不设置则默认使用框架内置的。
  • 使用示例:@AfterDate(date="2019-01-01 00:00:00", message="error message")

@Alpha

验证规则:

验证参数值必须是 大写字母 或 小写字母。

参数说明:

  • message: 验证失败时的错误提示,若不设置则默认使用框架内置的。
  • 使用示例: @Alpha(message="error message")

@AlphaDash

验证规则:

验证参数值必须是 大写字母 、 小写字母、数字、短横 -、下划线 _。

参数说明:

  • message: 验证失败时的错误提示,若不设置则默认使用框架内置的。
  • 使用示例: @AlphaDash(message="error message")

@AlphaNum

验证规则:

验证参数值必须是 大写字母 、 小写字母、数字。

参数说明:

  • message: 验证失败时的错误提示,若不设置则默认使用框架内置的。
  • 使用示例:@AlphaNum(message="error message")

@BeforeDate

验证规则:

验证参数值必须在某个日期之前,支持 字符串时间戳、格式化日期字符串(只支持 Y-m-d H:i:s)、整型时间戳,可在@IsString 或 @IsInt 类型注解中使用。

参数说明:

  • date: 要对比的日期值,只能是 Y-m-d H:i:s 格式。
  • message: 验证失败时的错误提示,若不设置则默认使用框架内置的。
  • 使用示例: @BeforeDate(date="2019-01-01 00:00:00", message="error message")

@Chs

验证规则:

验证参数值只能是 中文。

参数说明:

  • message: 验证失败时的错误提示,若不设置则默认使用框架内置的。
  • 使用示例: @Chs(message="error message")

@ChsAlpha

验证规则:

验证参数值必须是 中文、大写字母 、 小写字母。

参数说明:

  • message: 验证失败时的错误提示,若不设置则默认使用框架内置的。
  • 使用示例: @ChsAlpha(message="error message")

@ChsAlphaDash

验证规则:

验证参数值必须是 中文、大写字母 、 小写字母、数字、短横 -、下划线 _。

参数说明:

  • message: 验证失败时的错误提示,若不设置则默认使用框架内置的。
  • 使用示例: @ChsAlphaDash(message="error message")

@ChsAlphaNum

验证规则:

验证参数值必须是 中文、大写字母 、 小写字母、数字。

参数说明:

  • message: 验证失败时的错误提示,若不设置则默认使用框架内置的。
  • 使用示例: @ChsAlphaNum(message="error message")

@Confirm

验证规则:

验证参数值必须和另外一个字段参数值相同。

参数说明:

  • name: 需要确认对比的字段名,在类型注解中设置过的 name 或者是默认的 属性名。
  • message: 验证失败时的错误提示,若不设置则默认使用框架内置的。
  • 使用示例: @Confirm(name="field", message="error message")

@Different

验证规则:

验证参数值必须和另外一个字段参数值不同。

参数说明:

  • name: 需要确认对比的字段名,在类型注解中设置过的 name 或者是默认的 属性名。
  • message: 验证失败时的错误提示,若不设置则默认使用框架内置的。
  • 使用示例:@Different(name="field", message="error message")

@GreaterThan

验证规则:

验证参数值必须比另外一个字段参数值大,只支持 int 或 float, 字符串会被转化为 float 后进行对比。

参数说明:

  • name: 需要确认对比的字段名,在类型注解中设置过的 name 或者是默认的 属性名。
  • message: 验证失败时的错误提示,若不设置则默认使用框架内置的。
  • 使用示例: @GreaterThan(name="field", message="error message")

@LessThan

验证规则:

验证参数值必须比另外一个字段参数值小,只支持 int 或 float, 字符串会被转化为 float 后进行对比。

参数说明:

  • name: 需要确认对比的字段名,在类型注解中设置过的 name 或者是默认的 属性名。
  • message: 验证失败时的错误提示,若不设置则默认使用框架内置的。
  • 使用示例: @LessThan(name="field", message="error message")

@Date

验证规则:

验证参数值必须是日期格式,支持 字符串时间戳、格式化日期字符串(只支持 Y-m-d H:i:s)、整型时间戳,可在@IsString 或 @IsInt 类型注解中使用。

注意由于时间戳的特殊性默认为一个整型 大于 PHP_INT_MIN , 小于 PHP_INT_MAX 常量的数值均为有效时间戳。

参数说明:

  • message: 验证失败时的错误提示,若不设置则默认使用框架内置的。
  • 使用示例: @Date(message="error message")

@DateRange

验证规则:

验证参数值必须在某个日期范围之内(可以等于临界日期),支持 字符串时间戳、格式化日期字符串(只支持 Y-m-d H:i:s)、整型时间戳,可在@IsString 或 @IsInt 类型注解中使用。

参数说明:

  • start: 要对比的开始日期值,只能是 Y-m-d H:i:s 格式。
  • end: 要对比的结束日期值,只能是 Y-m-d H:i:s 格式。
  • message: 验证失败时的错误提示,若不设置则默认使用框架内置的。
  • 使用示例: @DateRange(start="2019-01-01 00:00:00",end="2019-01-01 00:00:00", message="error message")

@Dns

验证规则:

验证参数值必须是一个具有有效 DNS 记录域名或者ip,使用 checkdnsrr() 函数校验。

参数说明:

  • message: 验证失败时的错误提示,若不设置则默认使用框架内置的。
  • 使用示例: @Dns(message="error message")

@Email

验证规则:

验证参数值格式必须为邮箱

参数说明:

  • message: 验证失败时的错误提示,若不设置则默认使用框架内置的。
  • 使用示例: @Email(message="error message")

@Enum

验证规则:

验证参数值必须在枚举数组里面。

参数说明:

  • values: 枚举数组集合
  • message: 验证失败时的错误提示,若不设置则默认使用框架内置的。
  • 使用示例: @Enum(values={1,2,3},message="error message")

@File

验证规则:

验证此参数的值必须是文件,可以是单个文件,也可以是表单数组上传的多个文件。注意文件上传后文件域的获取需要通过 Swoft\Http\Message\Request 对象去获取。

参数说明:

  • message: 验证失败时的错误提示,若不设置则默认使用框架内置的。
  • 使用示例: @File(message="error message")

@FileMediaType

验证规则:

使用此条件前必须使用 @File 规则为基础。 验证每个上传的文件 mediaType 类型,支持表单数组,批量文件。

参数说明:

  • mediaType: mediaType类型数组。
  • message: 验证失败时的错误提示,若不设置则默认使用框架内置的。
  • 使用示例: @FileMediaType(mediaType={"image/gif","image/png"},message="error message")

@FileSize

验证规则:

使用此条件前必须使用 @File 规则为基础。 验证每个上传的文件尺寸大小(单位 byte 字节),支持表单数组,批量文件。

参数说明:

  • size: 文件尺寸大小,单位 byte。
  • message: 验证失败时的错误提示,若不设置则默认使用框架内置的。
  • 使用示例: @FileSize(size=1024,message="error message")

@FileSuffix

验证规则:

使用此条件前必须使用 @File 规则为基础。 验证每个上传的文件后缀名,支持表单数组,批量文件。

参数说明:

  • suffix: 后缀名数组。
  • message: 验证失败时的错误提示,若不设置则默认使用框架内置的。
  • 使用示例: @FileSuffix(suffix={"png","jpg"},message="error message")

@Ip

验证规则:

验证参数值必须是个IP类型。

参数说明:

  • message: 验证失败时的错误提示,若不设置则默认使用框架内置的。
  • 使用示例: @Ip(message="error message")

@Length

验证规则:

验证参数值长度限制。

参数说明:

  • min: 最小值(包含当前值)。
  • max: 最大值(包含当前值)。
  • message: 验证失败时的错误提示,若不设置则默认使用框架内置的。
  • 使用示例: @Length(min=1,max=4,message="error message")

@Low

验证规则:

验证参数值必须是小写字母。

参数说明:

  • message: 验证失败时的错误提示,若不设置则默认使用框架内置的。
  • 使用示例: @Low(message="error message")

@Max

验证规则:

最大值验证,必须是整数。

参数说明:

  • value 最大值(包含当前值)
  • message: 验证失败时的错误提示,若不设置则默认使用框架内置的。
  • 使用示例: @Max(value=5,message="error message")

@Min

验证规则:

最小值验证

参数说明:

  • value 最小值(包含当前值)
  • message: 验证失败时的错误提示,若不设置则默认使用框架内置的。
  • 使用示例: @Min(value=5,message="error message")

@Mobile

验证规则:

手机号验证。

参数说明:

  • message: 验证失败时的错误提示,若不设置则默认使用框架内置的。
  • 使用示例:@Mobile(message="error message")

@NotEmpty

验证规则:

参数值不能为空验证。

参数说明:

  • message: 验证失败时的错误提示,若不设置则默认使用框架内置的。
  • 使用示例: @NotEmpty(message="error message")

@NotInEnum

验证规则:

验证参数值必须不在枚举数组中。

参数说明:

  • values 枚举数组集合。
  • message: 验证失败时的错误提示,若不设置则默认使用框架内置的。
  • 使用示例: @NotInEnum(values={1,2,3},message="error message")

@NotInRange

验证规则:

验证参数值必须不在范围内

参数说明:

    • min: 最小值(包含当前值)。
  • max: 最大值(包含当前值)。
    • message: 验证失败时的错误提示,若不设置则默认使用框架内置的。
  • 使用示例: @NotInRange(min=1,max=5,message="error message")

@Pattern

验证规则:

正则表达式验证。

参数说明:

  • regex: 正则表达式。
  • message: 验证失败时的错误提示,若不设置则默认使用框架内置的。
  • 使用示例: @Pattern(regex="/^1\d{10}$/", message="error message")

@Range

验证规则:

参数值范围验证。

参数说明:

  • min: 最小值(包含当前值)。
  • max: 最大值(包含当前值)。
  • message: 验证失败时的错误提示,若不设置则默认使用框架内置的。
  • 使用示例: @Range(min=1,max=5,message="error message")

@Upper

验证规则:

验证参数值必须是大写字母。

参数说明:

  • message: 验证失败时的错误提示,若不设置则默认使用框架内置的。
  • 使用示例:@Upper(message="error message")

@Url

验证规则:

验证参数值必须是有效的URL格式,使用 filter_var()函数验证。

参数说明:

  • message: 验证失败时的错误提示,若不设置则默认使用框架内置的。
  • 使用示例: @Url(message="error message")

自定义验证器

常见的业务默认验证器就能解决,但是有些业务默认验证器是没法验证,此时就需要用户根据自己业务需求,定义满足自己业务的验证器。

自定义验证定义需要定义3个文件,注解文件,注解解析文件,验证器规则

简单示例

我们定义一个验证2个字段数据是否相等的验证器规则

1 注解定义

 

文件 App/Annotation/Mapping/Eq.php
<?php declare(strict_types=1);


namespace App\Annotation\Mapping;

use Doctrine\Common\Annotations\Annotation\Attribute;
use Doctrine\Common\Annotations\Annotation\Attributes;

/**
 * Class Eq
 *
 * @since 2.0
 *
 * @Annotation
 * @Attributes({
 *     @Attribute("message",type="string"),
       @Attribute("prop",type="string")
 * })
 */
class Eq
{
 /**
     * @var string
     */
 private $message = '';

 /**
     * @var string
     */
 private $name = '';

 private $prop = '';
 /**
         * StringType constructor.
         *
         * @param array $values
         */
 public function __construct(array $values)
 {
 if (isset($values['value'])) {
                $this->message = $values['value'];
 }
 if (isset($values['message'])) {
                $this->message = $values['message'];
 }
 if (isset($values['name'])) {
                $this->name = $values['name'];
 }
 if (isset($values['prop'])) {
                $this->prop = $values['prop'];
 }
 }

 /**
         * @return string
         */
 public function getMessage(): string
 {
 return $this->message;
 }

 /**
         * @return string
         */
 public function getName(): string
 {
 return $this->name;
 }

 /**
         * @return string
         */
 public function getProp(): string
 {
 return $this->prop;
 }
}

 

说明 这你定义其他验证器注解的时候只需要改变类名称,内容保持一样即可

文件 App/Annotation/Parser/EqParser.php
<?php declare(strict_types=1);

namespace App\Annotation\Parser;

use ReflectionException;
use Swoft\Annotation\Annotation\Mapping\AnnotationParser;
use Swoft\Annotation\Annotation\Parser\Parser;
use App\Annotation\Mapping\Eq;
use Swoft\Validator\Exception\ValidatorException;
use Swoft\Validator\ValidatorRegister;

/**
 * Class EqParser
 *
 * @AnnotationParser(annotation=Eq::class)
 */
class EqParser extends Parser
{
 /**
     * @param int $type
     * @param object $annotationObject
     *
     * @return array
     * @throws ReflectionException
     * @throws ValidatorException
     */
 public function parse(int $type, $annotationObject): array
 {
 if ($type != self::TYPE_PROPERTY) {
 return [];
 }
 ValidatorRegister::registerValidatorItem($this->className, $this->propertyName, $annotationObject);
 return [];
 }
}

 

说明 这个类是注解的解析类,你只需要修改注解 @AnnotationParser 参数 annotation 为你自己定义的注解定义类即可.同时别忘了改类名.

文件 App/Validator/Rule/EqRule.php
<?php declare(strict_types=1);


namespace App\Validator\Rule;

use App\Annotation\Mapping\Eq;
use Swoft\Bean\Annotation\Mapping\Bean;
use Swoft\Validator\Contract\RuleInterface;
use Swoft\Validator\Exception\ValidatorException;

/**
 * Class AlphaDashRule
 *
 * @Bean(Eq::class)
 */
class EqRule implements RuleInterface
{
 /**
     * @param array $data
     * @param string $propertyName
     * @param object $item
     * @param null $default
     *
     * @return array
     * @throws ValidatorException
     */
 public function validate(array $data, string $propertyName, $item, $default = null): array
 {
 if(!isset($data[$item->getProp()])){
 throw new ValidatorException($item->getProp()."必须要传入");
 }
 if($data[ $propertyName]==$data[$item->getProp()]){
 return  $data;
 }
 throw ValidatorException($item->getMessage());
 }
}

 

代码说明

  1. 首先需要定义Bean注解,并且 bean注解 并且值需要是你的 注解类的class名称 我们这里是 Eq
  2. 需要继承 RuleInterface 接口 并实现 validate 方法
  3. validate 方法有4个参数,下面介绍一下
  • $data 数据对象 传过来需要验证的的 k=>v 数组
  • $propertyName 需要验证的属性名称 也就是你注解加在哪个属性这里就是哪个属性名
  • $item 注解对象,可以调用注解的 getter 方法取得注解定义的参数
  • $default 默认值

 

使用示例

定义验证器

文件 App/Validator/TestValidator2.php

 

<?php declare(strict_types=1);


namespace App\Validator;

use App\Annotation\Mapping\Eq;
use Swoft\Validator\Annotation\Mapping\IsString;
use Swoft\Validator\Annotation\Mapping\Validator;

/**
 * Class TestValidator2
 *
 * @since 2.0
 *
 * @Validator(name="TestValidator2")
 */
class TestValidator2
{
 /**
     * @IsString()
     * @Eq(message="name和name1不一致",prop="name1")
     *
     * @var string
     */
 protected $name;


}

 

注意这里的 IsString 注解不能省,因为需要验证数据类型

定义使用

文件 App/Http/Controller/ValidatorController.php
<?php declare(strict_types=1);

namespace App\Http\Controller;

use App\Validator\TestValidator2;
use Swoft\Http\Message\Request;
use Swoft\Http\Server\Annotation\Mapping\Controller;
use Swoft\Http\Server\Annotation\Mapping\RequestMapping;
use Swoft\Validator\Annotation\Mapping\Validate;

/**
 * Class ValidatorController
 *
 * @Controller()
 */
class ValidatorController
{
 /**
     * Verify all defined fields in the TestValidator validator
     *
     * @RequestMapping("/testValidator)
     * @Validate(validator="TestValidator2")
     *
     * @param Request $request
     *
     * @return array
     */
 public function validateAll(Request $request): array
 {
 return $request->getParsedBody();
 }

}

控制台输出

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值