swoft 学习笔记之验证器
一、创建验证器
- @Validator(name="ValidatorName") 声明一个名字为 ValidatorName 的验证器
- 验证项是组成验证器的唯一条件,标记有类型注解的属性就是一个验证项,一个验证器可以有多个验证项
验证项
- 属性的默认值就是参数的默认值,如果属性没有定义默认值,代表参数没有定义默认值且必须传递。
- 一个属性必须定义一个类型注解,否则不是一个验证项且对参数验证无效。
- 一个属性可以多个条件注解,按照定义顺序验证数据。
- 默认属性名称就是需要验证的参数名称,也可以通过类型注解的 name 参数映射需要验证的字段名称。
- 若验证不通过时,将会抛出 Swoft\Validator\Exception\ValidatorException 异常。
类型注解
@IsInt、@IsArray、@IsString、@IsFloat、@IsBool
参数 name 指定需要验证字段名字,message 指定验证不通过时的错误信息
条件注解
@AfterDate、@Alpha、@AlphaDash、@AlphaNum、@BeforeDate、@Chs、@ChsAlpha等比较多,在此无需一一罗列,参考官方文档即可
使用条件注解的时候一定要注意引用正确的验证类
代码样例
验证器 TestValidator.php
<?php declare(strict_types=1);
namespace App\Validator;
use Swoft\Validator\Annotation\Mapping\AlphaDash;
use Swoft\Validator\Annotation\Mapping\Confirm;
use Swoft\Validator\Annotation\Mapping\IsString;
use Swoft\Validator\Annotation\Mapping\Length;
use Swoft\Validator\Annotation\Mapping\Validator;
/**
* Class TestValidator
* @Validator(name="TestValidator")
*/
class TestValidator
{
/**
* @IsString()
* @AlphaDash(message="名字必须是数字,字母,短横,下划线组合")
* @Length(min=4,max=20,message="名字长度在4~20之间")
* @var string
*/
protected $name;
/**
* @IsString()
* @AlphaDash(message="密码必须是数字,字母,短横,下划线组合")
* @Length(min=6,max=15,message="密码长度在6~15之间")
* @var string
*/
protected $password;
/**
* @IsString()
* @Confirm(name="password",message="确认密码不一致")
* @var string
*/
protected $confirmPassword;
}
控制器类 TestController.php
<?php declare(strict_types=1);
namespace App\Http\Controller;
use Swoft\Context\Context;
use Swoft\Http\Message\ContentType;
use Swoft\Http\Message\Request;
use Swoft\Http\Message\Response;
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 TestController
* @package App\Http\Controller
* @Controller(prefix="test")
*/
class TestController
{
/**
* @RequestMapping(route="register",method={RequestMethod::POST})
* @Validate(validator="TestValidator")
* @param Request $request
* @return Response
*/
public function register(Request $request):Response
{
$name = $request->post('name');
$password = $request->post('password');
$age = $request->post('age');
$data = [
'name' => $name,
'age' => $age ?? 18,
'password' => $password,
];
$response = Context::mustGet()->getResponse();
$response = $response->withStatus(201)
->withContentType(ContentType::JSON)
->withData($data);
return $response;
}
}
在控制器中使用 @Validate 进行验证
- validator 指定验证器名称
- fields 指定验证器里面验证的字段,这样可以高效的重复使用验证器
- type 默认 body,ValidateType::GET 验证 GET 请求 query 参数
- params 自定义验证器使用,传递给自定义验证器的参数
二、自定义验证规则
以定义一个正整数的验证规则为实例进行讲解
步骤一:声明注解命令
<?php declare(strict_types=1);
namespace App\Annotation\Mapping;
use Doctrine\Common\Annotations\Annotation\Attribute;
use Doctrine\Common\Annotations\Annotation\Attributes;
/**
* Class PositiveInteger
* @package App\Annotation\Mapping
* @Annotation //声明这个类是一个注解命令
* @Attributes({ //声明注解参数集合
* @Attribute("message",type="string") //声明注解具体的参数 name 参数的名字 type 参数值的类型
* })
*/
class PositiveInteger
{
/**
* @var string
*/
private $message = '';
/**
* PositiveInteger 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'];
}
}
/**
* @return string
*/
public function getMessage(): string
{
return $this->message;
}
}
步骤二:声明注解解析
注解命令要想能够执行,则还需要定义一个注解命令的解析器,需要继承
Swoft\Annotation\Annotation\Parser\Parser
类
<?php declare(strict_types=1);
use Swoft\Annotation\Annotation\Parser\Parser;
use Swoft\Annotation\Annotation\Mapping\AnnotationParser;
use Swoft\Validator\ValidatorRegister;
/**
* Class PositiveIntegerParser
* @AnnotationParser(annotation="PositiveInteger::class") //声明要解析的注解命令
*/
class PositiveIntegerParser extends Parser{
/**
* @param int $type
* @param object $annotationObject
* @return array
* @throws ReflectionException
* @throws \Swoft\Validator\Exception\ValidatorException
*/
public function parse(int $type,$annotationObject):array
{
if($type !== self::TYPE_PROPERTY){
return [];
}
//向验证器注册一个验证规则
ValidatorRegister::registerValidatorItem($this->className,
$this->propertyName,$annotationObject);
return [];
}
}
步骤三:声明一个验证规则
<?php declare(strict_types=1);
namespace App\Validator\Rule;
use Swoft\Bean\Annotation\Mapping\Bean;
use Swoft\Validator\Contract\RuleInterface;
use Swoft\Validator\Exception\ValidatorException;
/**
* Class PositiveIntegerRule
* @package App\Validator\Rule
* @Bean(PositiveInteger::class) //验证器内部是通过 Bean 容器来获得到我们的验证规则的
*/
class PositiveIntegerRule 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
{
$message = $item->getMessage();
if( !isset($data[$propertyName]) && $default == null){
$message = empty($message) ? sprintf("s% 不能为空",$propertyName) : $message;
throw new ValidatorException($message,400);
}
if (is_numeric($data[$propertyName])
&& is_int($data[$propertyName] + 0)
&& ($data[$propertyName] + 0) > 0) {
return [$data];
}
$message = empty($message) ? sprintf("s% 必须是正整数",$propertyName) : $message;
throw new ValidatorException($message,400);
}
}
本作品采用《CC 协议》,转载必须注明作者和本文链接
https://www.supjos.cn/archives/89.html
合伙搞个原生注解的项目不?
大兄弟,终于找到你了。 这东西麻烦得很, 请再详细点, thanks
例如type字段可以不传入,但如果传入的话type必须是int类型,这样怎么实现?
楼主,问你一个问题,验证器能发与中间件使用,我想把数据检查方法中间件里面,中间件负责权限检查,数据检查,jwt检查,到控制器的数据都是安全的,这样能行么?能否给一个示例,十分感谢
楼主,swoft的验证器 如果一个参数不是必须,传了需要验证不传 可以忽略怎么写?,还有就是我在验证器离写了一个protected $name; 文档说没给默认是必传,但是我没给 验证也通过了是怎么回事