Skip to main content
  1. All Posts/

php-validate

Tools PHP

PHP Validate



一个简洁小巧且功能完善的php验证、过滤库。

  • 简单方便,支持添加自定义验证器
  • 支持前置验证检查, 自定义如何判断非空
  • 支持将规则按场景进行分组设置。或者部分验证
  • 支持在进行验证前对值使用过滤器进行净化过滤内置过滤器
  • 支持在进行验证前置处理和后置处理独立验证处理
  • 支持自定义每个验证的错误消息,字段翻译,消息翻译,支持默认值
  • 支持基本的数组检查,数组的子级('goods.apple')值检查, 通配符的子级检查 ('users.*.id' 'goods.*')
  • 方便的获取错误信息,验证后的安全数据获取(只会收集有规则检查过的数据)
  • 已经内置了大量的常用的验证器内置验证器
  • 规则设置参考 yii, laravel, Respect/Validation
  • 独立的过滤器 InhereValidateFilterFiltration,可单独用于数据过滤

两种规则配置方式

validate 同时支持两种规则配置方式,对应了两种规则的收集解析策略。

多字段单规则

  • Validation|RuleValidation: 每条规则中,允许多个字段,但只能有一个验证器。 (规则配置类似于Yii)

配置示例: (本文档的示例都是这种)

[
    ['tagId,userId,name,email,freeTime', 'required', ...],
    // ... ...
];

单字段多规则

  • FieldValidation: 每条规则中,只能有一个字段,但允许多个验证器。 (规则配置类似于Laravel)
  • FieldValidation: 不支持验证器each

配置示例:

[
    ['field', 'required|string:5,10|...', ...],
    // ... ...
]

更多配置示例请参看 像Laravel一样配置

项目地址

安装

composer require inhere/php-validate
# or
# composer require inhere/php-validate ^3.0

注意

  • master 分支是要求 php8.1+ 的(推荐使用)
  • 2.x 分支是支持 php7.1+,但是基本上不再维护。
  • 1.x 分支是支持php5的代码分支,但是基本上不再维护。

立即使用

方式1: 直接使用类 Validation

需要快速简便的使用验证时,可直接使用 InhereValidateValidation

use InhereValidateValidation;

class SomeController
{
    public function demoAction()
    {
        $v = Validation::check($_POST,[
            // add rule
            ['title', 'min', 40],
            ['freeTime', 'number'],
        ]);

        if ($v->isFail()) {
            var_dump($v->getErrors());
            var_dump($v->firstError());
        }

        // $postData = $v->all(); // 原始数据
        $safeData = $v->getSafeData(); // 验证通过的安全数据

        $db->save($safeData);
    }
}

方式2: 继承类 Validation

创建一个新的class,并继承 InhereValidateValidation。用于一个(或一系列相关)请求的验证, 相当于 laravel 的 表单请求验证

此方式是最为完整的使用方式,可以配置规则,设置字段翻译,设置自定义的错误消息等

use InhereValidateValidation;

class PageRequest extends Validation
{
    # 进行验证前处理,返回false则停止验证,但没有错误信息,可以在逻辑中调用 addError 增加错误信息
    public function beforeValidate(): bool
    {
        return true;
    }
    # 进行验证后处理,该干啥干啥
    public function afterValidate(): bool
    {
        return true;
    }


    public function rules(): array
    {
        return [
            // 字段必须存在且不能为空
            ['tagId,title,userId,freeTime', 'required'],

            // 4<= tagId <=567
            ['tagId', 'size', 'min'=>4, 'max'=>567, 'filter' => 'int'],

            // title length >= 40. 注意只需一个参数的验证,无需加 key, 如这里的 40
            ['title', 'min', 40, 'filter' => 'trim'],

            // 大于 0
            ['freeTime', 'number'],

            // 含有前置条件
            ['tagId', 'number', 'when' => function($data) {
                return isset($data['status']) && $data['status'] > 2;
            }],

            // 在验证前会先过滤转换为 int。并且仅会在指明场景名为 'scene1' 时规则有效
            ['userId', 'number', 'on' => 'scene1', 'filter' => 'int'],
            ['username', 'string', 'on' => 'scene2', 'filter' => 'trim'],

            // 使用自定义正则表达式
            ['username', 'regexp' ,'/^[a-z]w{2,12}$/'],

            // 自定义验证器,并指定当前规则的消息
            ['title', 'custom', 'msg' => '{attr} error msg!' ],

            // 直接使用闭包验证
            ['status', function($status) {
                if (is_int($status) && $status > 3) {
                    return true;
                }
                return false;
            }],

            // 标记字段是安全可靠的 无需验证
            ['createdAt, updatedAt', 'safe'],
        ];
    }

    // 定义不同场景需要验证的字段。
    // 功能跟规则里的 'on' 类似,两者尽量不要同时使用,以免混淆。
    public function scenarios(): array
    {
        return [
            'create' => ['user', 'pwd', 'code'],
            'update' => ['user', 'pwd'],
        ];
    }

    // 定义字段翻译
    public function translates(): array
    {
        return [
          'userId' => '用户Id',
        ];
    }

    // 自定义验证器的提示消息, 默认消息请看 {@see ErrorMessageTrait::$messages}
    public function messages(): array
    {
        return [
           // 使用验证器名字指定消息
          'required' => '{attr} 是必填项。',
          // 可以直接针对字段的某个规则进行消息定义
          'title.required' => 'O, 标题是必填项。are you known?',
        ];
    }

    // 添加一个验证器。必须返回一个布尔值标明验证失败或成功
    protected function customValidator($title): bool
    {
        // some logic ...
        // $this->getRaw('field'); 访问 data 数据

        return true; // Or false;
    }
}
  • 使用
// 验证 POST 数据
$v = PageRequest::check($_POST);

// 验证失败
if ($v->isFail()) {
    var_dump($v->getErrors());
    var_dump($v->firstError());
}

// 验证成功 ...
$safeData = $v->getSafeData(); // 验证通过的安全数据
// $postData = $v->all(); // 原始数据

$db->save($safeData);

方式3: 使用trait ValidationTrait

创建一个新的class,并使用 Trait InhereValidateValidationTrait

此方式是高级自定义的使用方式, 可以方便的嵌入到其他类中。

如下,嵌入到一个数据模型类中, 实现一个简单的模型基类,添加数据库记录前自动进行验证

class DataModel
{
    use InhereValidateValidationTrait;

    protected $data = [];

    protected $db;

    /**
     * @param array $data
     * @return $this
     */
    public function load(array $data)
    {
        $this->data = $data;

        return $this;
    }

    public function create()
    {
        if ($this->validate()->isFail()) {
            return false;
        }

        return $this->db->insert($this->getSafeData());
    }
}

使用:

// on model class
class UserModel extends DataModel
{
    public function rules(): array
    {
        return [
            ['username, passwd', 'required'],
            ['passwd', 'compare', 'repasswd', 'on' => 'create'],
            ['username', 'string', 'min' => 2, 'max' => 20, 'on' => 'create' ],
            ['id', 'number', 'on' => 'update' ], // 仅作用于场景 update
            ['createdAt, updatedAt', 'safe'],
        ];
    }
}

// on controller action ...
class UserController
{
    // in action
    // @api /user/add
    public function addAction()
    {
        $model = new UserModel;
        // 载入提交数据并设定场景为: create
        $model->load($_POST)->atScene('create');

        if (!$ret = $model->create()) {
            exit($model->firstError());
        }

        echo "add success: userId = $ret";
    }
}