精华内容
下载资源
问答
  • 展开全部参数检62616964757a686964616fe59b9ee7ad9431333366303234验针对参数做的假设,非参数检验针对总体分布情况做的假设,这个区分参数检验和非参数检验的一个重要特征。参数检验和非参数检验的本质区别:...

    展开全部

    参数检62616964757a686964616fe59b9ee7ad9431333366303234验是针对参数做的假设,非参数检验是针对总体分布情况做的假设,这个是区分参数检验和非参数检验的一个重要特征。

    参数检验和非参数检验的本质区别:

    1.参数检验要利用到总体的信息(总体分布、总体的一些参数特征如方差),以总体分布和样本信息对总体参数作出推断;非参数检验不需要利用总体的信息(总体分布、总体的一些参数特征如方差),以样本信息对总体分布作出推断。

    2.参数检验只能用于等距数据和比例数据,非参数检验主要用于记数数据。也可用于等距和比例数据,但精确性就会降低。

    扩展资料:

    参数检验与非参数检验的优缺点。

    1)参数检验:优点是符合条件时,检验效率高;其缺点是对资料要求严格,如等级数据、非确定数据(>50mg)不能使用参数检验,而且要求资料的分布型已知和总体方差相等。

    2)非参数检验:优点是应用范围广、简便、易掌握;缺点是若对符合参数检验条件的资料用非参数检验,则检验效率低于参数检验。如无效假设是正确的,非参数法与参数法一样好,但如果无效假设是错误的,则非参数检验效果较差,如需检验出同样大小的差异的差异往往需要较多的资料。

    另一点是非参数检验统计量是近似服从某一部分,检验的界值表也是有近似的(如配对秩和检验)因此其结果有一定近似性。

    1、提出检验假设又称无效假设,符号是H0;备择假设的符号是H1。

    H0:样本与总体或样本与样本间的差异是由抽样误差引起的;

    H1:样本与总体或样本与样本间存在本质差异;

    预先设定的检验水准为0.05;当检验假设为真,但被错误地拒绝的概率,记作α,通常取α=0.05或α=0.01。

    2、选定统计方法,由样本观察值按相应的公式计算出统计量的大小,如X2值、t值等。根据资料的类型和特点,可分别选用Z检验,T检验,秩和检验和卡方检验等。

    3、根据统计量的大小及其分布确定检验假设成立的可能性P的大小并判断结果。若P>α,结论为按α所取水准不显著,不拒绝H0,即认为差别很可能是由于抽样误差造成的,在统计上不成立。

    如果P≤α,结论为按所取α水准显著,拒绝H0,接受H1,则认为此差别不大可能仅由抽样误差所致,很可能是实验因素不同造成的,故在统计上成立。P值的大小一般可通过查阅相应的界值表得到。

    两独立样本的非参数检验是在对总体分布不甚了解的情况下,通过对两组独立样本的分析来推断样本来自的两个总体的分布等是否存在显著差异的方法。独立样本是指在一个总体中随机抽样对在另一个总体中随机抽样没有影响的情况下所获得的样本。

    SPSS中提供了多种两独立样本的非参数检验方法,其中包括曼-惠特尼U检验、K-S检验、W-W游程检验、极端反应检验等。

    某工厂用甲乙两种不同的工艺生产同一种产品。如果希望检验两种工艺下产品的使用是否存在显著差异,可从两种工艺生产出的产品中随机抽样,得到各自的使用寿命数据。

    展开全文
  • 在实现服务端的API接口时,对于每一个接口的每一个参数,都应该检测其取值是否合法,以免错误的数据输入到系统中。这个工作可以说是费时费力,但又不得做。而且PHP本身弱类型语言,不但要验证取值,还要验证数据...

    WebGeeker-Validation: 一个强大的 PHP 参数验证器

    项目地址: github 码云

    用于对API接口的请求参数进行合法性检查。

    在实现服务端的API接口时,对于每一个接口的每一个参数,都应该检测其取值是否合法,以免错误的数据输入到系统中。这个工作可以说是费时费力,但又不得不做。而且PHP本身是弱类型语言,不但要验证取值,还要验证数据的类型是否符合,这就更复杂了。

    本工具就是针对这个工作而设计的,能够有效地减少编码量,代码可读性好。

    看看下面这段代码,可以对用法有个大概印象,应该不难看懂:

    $params = $request->query(); // 获取GET参数
    
    // 验证(如果验证不通过,会抛出异常)
    Validation::validate($params, [
        "offset" => "IntGe:0",
        "count" => "Required|IntGeLe:1,200",
    ]);
    

    支持多种数据类型的校验:整型、浮点型、bool型、字符串、数组、对象、文件、日期时间,能够验证嵌套的数据结构中的参数,还支持带条件判断的验证。

    • 目录
    • 1 简介
      • 1.1 为什么要写这样一个工具?
      • 1.2 特点
      • 1.3 一个简单示例
    • 2 安装
    • 3 快速上手
      • 3.1 一个完整的示例(不使用任何框架)
      • 3.2 验证不通过的错误处理
      • 3.3 在第三方框架中的用法
    • 4 详细使用方法
      • 4.1 验证整型参数
      • 4.2 验证浮点型参数
      • 4.3 验证bool型参数
      • 4.4 验证字符串型参数
      • 4.5 验证数组型、对象型、文件型、日期时间型参数
      • 4.6 验证器串联(与)
      • 4.7 Required 验证器
      • 4.8 忽略所有 Required 验证器
      • 4.9 嵌套参数的验证
      • 4.10 条件判断型验证器
      • 4.11 验证规则并联(或)
      • 4.12 关于特殊值null, "",0,false的问题
      • 4.13 关于基本数据类型与字符串的关系
      • 4.14 自定义错误信息输出文本
      • 4.15 国际化
      • 4.16 国际化(0.4版之前)
    • A 附录 - 验证器列表
      • A.1 整型
      • A.2 浮点型
      • A.3 bool型
      • A.4 字符串型
      • A.5 数组型
      • A.6 对象型
      • A.7 文件型
      • A.8 日期和时间型
      • A.9 条件判断型
      • A.10 其它验证器

    1 简介

    1.1 为什么要写这样一个工具?

    我在使用Laravel框架的时候,Laravel提供了一个参数验证工具,不过用起来不怎么顺畅: 每一个验证都写一个验证类(继承XXX),这样太麻烦,而且系统中会多出许多许多的类;如果这些类在多处被复用,或者为了“更加”复用(减少重复代码),再在这些类之间搞出很多的继承关系,那么这些类的维护本身就是一个大问题; 验证器有“一词多义”的问题。比如它有一个size验证器,它同时支持验证字符串、整型、文件等多种类型的参数,针对不同数据类型size的含义不一样。这就好比你去背英语单词,有那么一些英语单词,它有很多很多意思,不同的语境下有不同的含义。比如"present"这个单词,它既有“呈现”、“出席”的意思,也有“礼物”的意思。这种一词多义的单词最让人头疼了,搞不清它到底什么意思,而且记不住啊。

    为了解决这些问题,所以才写了这么一个工具。

    1.2 特点

    1. 每个功能特性都有单元测试(共有 41 tests, 369 assertions)
    2. 支持无限嵌套的数据结构的验证(参考 1.3 节的例子)
    3. 支持条件验证,根据参数取值不同,应用不同的验证规则(参考 1.3 节的例子)
    4. 支持正则表达式验证
    5. 简洁,验证逻辑一目了然(参考后面的例子)
    6. 轻量,不需要定义和维护各种验证classes
    7. 验证器语义明确,没有“一词多义”的问题
    8. 易学易记。比如整型验证器都是以"Int"开头,浮点型验证器都是以"Float"开头,等等。唯一不符合这一规则的是字符串型验证器,它们一部分以"Str"开头的,但也有一部分不以"Str"开头,比如Regexp, Ip, Email, Url等。
    9. 不绑定任何一个框架,无任何依赖。你可以在任何一个框架中使用这个工具,就算你不使用框架,也可以使用本工具。

    1.3 一个简单示例

    下面这个示例展示了一个查询获取用户投诉列表的Request参数的验证(注意其中的条件验证和针对嵌套数据结构的验证):

    //验证规则
    $validations = [
        "offset" => "IntGe:0", // 参数offset应该大于等于0
        "count" => "Required|IntGeLe:1,200", // 参数count是必需的且大于等于1小于等于200
        "type" => "IntIn:1,2", // 参数type可取值为: 1, 2
        "state" => [
            'IfIntEq:type,1|IntEq:0', // 如果type==1(批评建议),那么参数state只能是0
            'IfIntEq:type,2|IntIn:0,1,2', // 如果type==2(用户投诉),那么参数state可取值为: 1, 2, 3
        ],
        "search.keyword" => "StrLenGeLe:1,100", // search.keyword 应该是一个长度在[1, 100]之间的字符串
        "search.start_time" => "Date", // search.start_time 应该是一个包含合法日期的字符串
        "search.end_time" => "Date", // search.end_time 应该是一个包含合法日期的字符串
    ];
    
    // 待验证参数
    $params = [
        "offset" => 0, // 从第0条记录开始
        "count" => 10, // 最多返回10条记录
        "type" => 2, // 1-批评建议, 2-用户投诉
        "state" => 0, // 0-待处理, 1-处理中, 2-已处理
        "search" => [ // 搜索条件
            "keyword" => '硬件故障', // 关键字
            "start_time" => "2018-01-01", // 起始日期
            "end_time" => "2018-01-31", // 结束日期
        ],
    ];
    
    // 验证(如果验证不通过,会抛出异常)
    Validation::validate($params, $validations);
    

    2 安装

    通过Composer安装

    composer require webgeeker/validation:^0.4

    3 快速上手

    3.1 一个完整的示例(不使用任何框架)

    这个例子直接验证$_POST(POST表单)中的参数,展示了最基本的用法

    <?php
    include "vendor/autoload.php";
    
    use WebGeekerValidationValidation;
    
    try {
        Validation::validate($_POST, [
            "offset" => "IntGe:0", // 参数offset应该大于等于0
            "count" => "Required|IntGeLe:1,200", // 参数count是必需的且大于等于1小于等于200
        ]);
    } catch (Exception $e) {
        echo $e->getMessage();
    }
    

    注意:验证不通过会抛出异常,该异常中包含有错误描述信息

    3.2 验证不通过的错误处理

    如果验证不通过,Validation::validate(...)方法会抛出异常,建议在框架层面统一捕获这些异常,提取错误描述信息并返回给客户端。

    3.3 在第三方框架中的用法

    第三方框架一般会提供Request对象,可以取到GET, POST参数(以Laravel为例)

    //$params = $request->query(); // 获取GET参数
    $params = $request->request->all(); // 获取POST参数
    
    // 验证(如果验证不通过,会抛出异常)
    Validation::validate($params, [
        // 此处省略验证规则
    ]);
    

    4 详细使用方法

    4.1 验证整型参数

    整型验证器全部以"Int"开头,用于验证整型数值(如123)或整型字符串(如"123")。其它数据类型均不匹配。

    "size" => "IntGeLe:1,100"
    

    这条验证要求参数"size"是整数,并且大于等于1,小于等于100。

    完整的整型验证器的列表参考附录 A.1 。

    4.2 验证浮点型参数

    浮点型验证器全部以"Float"开头,用于验证浮点型数值(如1.0)、浮点型字符串(如"1.0")、整型数值(如123)或整型字符串(如"123")。其它数据类型均不匹配。

    "height" => "FloatGeLe:0.0,100.0"
    

    这条验证要求参数"height"是浮点数,并且大于等于0,小于等于100.0。

    完整的浮点型验证器的列表参考附录 A.2 。

    4.3 验证bool型参数

    bool型验证器只有两个: Bool: 合法的取值为: true, false, "true", "false"(字符串忽略大小写)。 BoolSmart: 合法的取值为: true, false, "true", "false", 1, 0, "1", "0", "yes", "no", "y", "n"(字符串忽略大小写)

    "accept" => "BoolSmart"
    

    完整的bool型验证器的列表参考附录 A.3 。

    4.4 验证字符串型参数

    字符串型验证器不全以"Str"开头。只接收字符串型数据,其它数据类型均不匹配。

    例1:

    "name" => "StrLenGeLe:2,20"
    

    这条验证要求参数"name"是字符串,长度在2-20之间(字符串长度是用mb_strlen()来计算的)。

    例2:

    "comment" => "ByteLenLe:1048576"
    

    这条验证要求参数"comment"是字符串,字节长度不超过1048576(字节长度是用strlen()来计算的)。

    例3:

    "email" => "Email"
    

    这条验证要求参数"email"是必须是合法的电子邮件地址。

    例4(正则表达式验证):

    "phone" => "Regexp:/^1(3[0-9]|4[579]|5[0-35-9]|7[0135678]|8[0-9]|66|9[89])d{8}$/"
    

    这条验证要求参数"phone"是合法的手机号。

    关于正则表达式中的哪些特殊字符需要转义的问题,只需要用 preg_match() 函数验证好,如:

    preg_match('/^string$/', $string);

    然后把两个'/'号及其中间的部分拷贝出来,放在Regexp:后面即可,不需要再做额外的转义,即使正则中有'|'这种特殊符号,也不需要再转义。

    完整的字符串型验证器的列表参考附录 A.4 。

    4.5 验证数组型、对象型、文件型、日期时间型参数

    参考附录A.5-A.8

    4.6 验证器串联(与)

    一条规则中可以有多个验证器前后串联,它们之间是“AND”的关系,如:

    "file" => "FileMaxSize:10m|FileImage"
    

    这个验证要求参数"file"是一个图像文件,并且文件大小不超过10m

    4.7 Required 验证器

    • Required验证器要求参数必须存在,且其值不能为null(这个是PHP的null值,而不是字符串"null")(参数值为null等价于参数不存在)。
    • 如果多个验证器串联,Required验证器必须在其它验证器前面。
    • 如果还有条件验证器,Required必须串联在条件验证器后面。
    • 如果验证规则中没有 Required,当参数存在时才进行验证,验证不通过会抛异常;如果参数不存在,那么就不验证(相当于验证通过)

    例:

    "size" => "Required|StrIn:small,middle,large"
    

    该验证要求参数"size"必须是字符串的"small", "middle"或者"large"。

    4.8 忽略所有 Required 验证器

    比如当创建一个用户时,要求姓名、性别、年龄全部都要提供;但是当更新用户信息时,不需要提供全部信息,提供哪个信息就更新哪个信息。

    $validations = [
        "name" => "Required|StrLenGeLe:2,20",
        "sex" => "Required|IntIn:0,1",
        "age" => "Required|IntGeLe:1,200",
    ];
    
    $userInfo = [
        "name" => "tom",
        "sex" => "0",
        "age" => "10",
    ];
    Validation::validate($userInfo, $validations); // 创建用户时的验证
    
    unset($userInfo["age"]); // 删除age字段
    Validation::validate($userInfo, $validations, true); // 更新用户信息时的验证
    

    注意上面代码的最后一行:validate()函数的第三个参数为true表示忽略所有的 Required 验证器。

    这样我们就只需要写一份验证规则,就可以同时用于创建用户和更新用户信息这两个接口。

    4.9 嵌套参数的验证

    下面这个例子展示了包含数组和对象的嵌套的参数的验证:

    $params = [
        "comments" => [
            [
                "title" => "title 1",
                "content" => "content 1",
            ],
            [
                "title" => "title 1",
                "content" => "content 1",
            ],
            [
                "title" => "title 1",
                "content" => "content 1",
            ],
        ]
    ];
    
    $validations = [
        "comments[*].title" => "Required|StrLenGeLe:2,50",
        "comments[*].content" => "Required|StrLenGeLe:2,500",
    ];
    
    Validation::validate($params, $validations);
    

    4.10 条件判断型验证器

    条件判断型验证器都以"If"开头。

    比如你想招聘一批模特,男的要求180以上,女的要求170以上,验证可以这样写:

    $validations = [
        "sex" => "StrIn:male,female",
        "height" => [
            "IfStrEq:sex,male|IntGe:180",
            "IfStrEq:sex,female|IntGe:170",
        ],
    ];
    

    参数"sex"的值不同,参数"height"的验证规则也不一样。

    完整的条件判断型验证器的列表参考附录 A.9 。

    4.11 验证规则并联(或)

    多条验证规则可以并联,它们之间是“或”的关系,如

    "type" => [
        "StrIn:small,middle,large",
        "IntIn:1,2,3",
    ]
    

    上面这条验证要求参数"type"既可以是字符串"small", "middle"或"large",也可以整型的1, 2或3

    验证规则并联不是简单的“或”的关系,具体验证流程如下: 1. 按顺序验证这些规则,如果有一条验证规则通过, 则该参数验证通过。 2. 如果全部验证规则都被忽略(If验证器条件不满足,或者没有Required验证器并且该参数不存在,或者有0条验证规则),也算参数验证通过。 3. 上面两条都不满足, 则该参数验证失败。

    这些规则如果要完全理清并不是一件容易的事,所以不建议使用验证规则并联,也尽量不要设计需要这种验证方式的参数。

    4.12 关于特殊值null, ""0false的问题

    这些特殊的值是不等价的,它们是不同的数据类型(需要用不同的验证器去验证): ""是字符串。 0是整型。 false是bool型。 null是PHP的空。在本工具中它有特殊的含义。

    如果某个参数的值为null,则本工具会视为该参数不存在。

    比如下面两个array对于本工具来说是等价的.

    $params = [
        "name" => "hello",
    ];
    

    $params = [
        "name" => "hello",
        "comment" => null,
    ];
    

    是等价的。

    4.13 关于基本数据类型与字符串的关系

    对于以下url地址

    http://abc.com/index.php?p1=&&p2=hello&&p3=123

    我们将得到的参数数组:

    $params = [
        "p1" => "",
        "p2" => "hello",
        "p3" => "123",
    ];
    

    注意 参数"p1"的值为空字符串"",而不是null 参数"p3"的值为字符串"123",而不是整型123。 * GET方式的HTTP请求是传递不了null值的。

    本工具的所有验证器都是强类型的,"Int"验证的是整型,"Float"验证的是浮点型,"Str*"验证的是字符串型,数据类型不匹配,验证是通不过的。但是字符串类型是个例外。

    因为常规的HTTP请求,所有的基本数据类型最终都会转换成字符串,所以: 整型123和字符串"123"均可以通过验证器"Int"的验证; 浮点型123.0和字符串"123.0"均可以通过验证器"Float"的验证; bool型true和字符串"true"均可以通过验证器"Bool"的验证; 但是null值和字符串"null"永远不等价,字符串"null"就只是普通的字符串。

    4.14 自定义错误信息输出文本

    如果参数验证不通过,Validation::validate()方法会抛出异常,这个异常会包含验证不通过的错误信息描述的文本。

    但是这个描述文本对用户来说可能不那么友好,我们可以通过两个伪验证器来自定义这些文本: Alias 用于自定义参数名称(这个名称会与内部的错误信息模版相结合,生成最终的错误信息描述文本) >>> 用于自定义错误描述文本(这个文本会完全取代模版生成的错误描述文本)。

    看下面的例子:

    $params = [
        "title" => "a",
    ];
    
    Validation::validate($params, [
        "title" => "Required|StrLenGeLe:2,50",
    ]); // 抛出异常的错误描述为:“title”长度必须在 2 - 50 之间
    
    Validation::validate($params, [
        "title" => "Required|StrLenGeLe:2,50|Alias:标题", // 自定义参数名称
    ]); // 抛出异常的错误描述为:“标题”长度必须在 2 - 50 之间
    
    Validation::validate($params, [
        "title" => "Required|StrLenGeLe:2,50|>>>:标题长度应在2~50之间", // 自定义错误信息描述文本
    ]); // 抛出异常的错误描述为:标题长度应在2~50之间
    

    参考附录A.10获取更详细的信息

    4.15 国际化

    从0.4版开始: 使用新的静态成员变量 $langCode2ErrorTemplates 来进行“错误提示信息模版”的翻译,主要目的是简化格式(感谢 @gitHusband 的建议)。 旧的翻译表 $langCodeToErrorTemplates 仍然有效,已有代码无需修改(参考下一节)。如果新旧翻译表同时提供,优先新的,新表中查不到再使用旧的。

    要支持国际化,需要自定义一个类,继承WebGeekerValidationValidation,重载两个静态成员变量: $langCode2ErrorTemplates用于提供“错误提示信息模版”的翻译对照表。完整的错误提示信息模版列表可以在WebGeekerValidationValidation::$errorTemplates成员变量中找到 $langCodeToTranslations用于提供“自定义参数名称”(由Alias指定)和“自定义错误描述文本”(由>>>指定)的翻译对照表。

    下面提供一个示例类:

    class MyValidation extends Validation
    {
        // “错误提示信息模版”翻译对照表
        protected static $langCodeToErrorTemplates = [
            "zh-tw" => [
                'Int' => '“{{param}}”必須是整數', //  
                'IntGt' => '“{{param}}”必須大於 {{min}}',
                'Str' => '“{{param}}”必須是字符串',
            ],
            "en-us" => [
                'Int' => '{{param}} must be an integer',
                'IntGt' => '{{param}} must be greater than {{min}}',
                'Str' => '{{param}} must be a string',
            ],
        ];
    
        // 文本翻译对照表
        protected static $langCodeToTranslations = [
            "zh-tw" => [
                "变量" => "變量", //  
                "变量必须是整数" => "變量必須是整數", // ⭐
            ],
            "en-us" => [
                "变量" => "variable",
                "变量必须是整数" => "variable must be an integer",
            ],
        ];
    }
    

    注意: 语言代码是区分大小写的,建议全部用小写,如"zh-cn", "en-us"等。 语言代码的名称是自定义的,你可以随便起名,比如"abc"(建议使用标准的语言代码)。

    使用这个MyValidation类来进行验证,就可以实现文本的翻译了。

    MyValidation::setLangCode("zh-tw"); // 设置语言代码
    
    MyValidation::validate(["var" => 1.0], [
        "var" => "Int", // 既没有Alias,也没有>>>,只会翻译错误提示信息模版(对应 那行)
    ]); // 会抛出异常:“var”必須是整數
    
    MyValidation::validate(["var" => 1.0], [
        "var" => "Int|Alias:变量", // 有Alias,除了翻译错误提示信息模版外,还会翻译参数名称(对应 那行)
    ]); // 会抛出异常:“變量”必須是整數
    
    MyValidation::validate(["var" => 1.0], [
        "var" => "Int|>>>:变量必须是整数", // 有>>>,会翻译自定义错误描述文本(对应⭐那行)
    ]); // 会抛出异常:變量必須是整數
    

    如果提供了错误的语言代码,或者没有找到翻译的文本,那么就不翻译,输出原始的文本。

    4.16 国际化(0.4版之前)

    (如果你使用的是0.4及之后的版本,建议使用新的国际化方案(参考上一节),更简洁一点)

    要支持国际化,需要自定义一个类,继承WebGeekerValidationValidation,重载两个静态成员变量: $langCodeToErrorTemplates用于提供“错误提示信息模版”的翻译对照表。完整的错误提示信息模版列表可以在WebGeekerValidationValidation::$errorTemplates成员变量中找到 $langCodeToTranslations用于提供“自定义参数名称”(由Alias指定)和“自定义错误描述文本”(由>>>指定)的翻译对照表。

    下面提供一个示例类:

    class MyValidation extends Validation
    {
        // “错误提示信息模版”翻译对照表
        protected static $langCodeToErrorTemplates = [
            "zh-tw" => [
                "“{{param}}”必须是整数" => "“{{param}}”必須是整數", //  
                "“{{param}}”必须是字符串" => "“{{param}}”必須是字符串",
            ],
            "en-us" => [
                "“{{param}}”必须是整数" => "{{param}} must be a integer",
                "“{{param}}”必须是字符串" => "{{param}} must be a string",
            ],
        ];
    
        // 文本翻译对照表
        protected static $langCodeToTranslations = [
            "zh-tw" => [
                "变量" => "變量", //  
                "变量必须是整数" => "變量必須是整數", // ⭐
            ],
            "en-us" => [
                "变量" => "variable",
                "变量必须是整数" => "variable must be an integer",
            ],
        ];
    }
    

    注意: 语言代码是区分大小写的,建议全部用小写,如"zh-cn", "en-us"等。 语言代码的名称是自定义的,你可以随便起名,比如"abc"(建议使用标准的语言代码)。

    使用这个MyValidation类来进行验证,就可以实现文本的翻译了。

    MyValidation::setLangCode("zh-tw"); // 设置语言代码
    
    MyValidation::validate(["var" => 1.0], [
        "var" => "Int", // 既没有Alias,也没有>>>,只会翻译错误提示信息模版(对应 那行)
    ]); // 会抛出异常:“var”必須是整數
    
    MyValidation::validate(["var" => 1.0], [
        "var" => "Int|Alias:变量", // 有Alias,除了翻译错误提示信息模版外,还会翻译参数名称(对应 那行)
    ]); // 会抛出异常:“變量”必須是整數
    
    MyValidation::validate(["var" => 1.0], [
        "var" => "Int|>>>:变量必须是整数", // 有>>>,会翻译自定义错误描述文本(对应⭐那行)
    ]); // 会抛出异常:變量必須是整數
    

    如果提供了错误的语言代码,或者没有找到翻译的文本,那么就不翻译,输出原始的文本。

    A 附录 - 验证器列表

    A.1 整型

    整型验证器全部以"Int"开头。

    | 整型验证器 | 示例 | 说明 | | :------| :------ | :------ | | Int | Int | “{{param}}”必须是整数 | | IntEq | IntEq:100 | “{{param}}”必须等于 {{value}} | | IntGt | IntGt:100 | “{{param}}”必须大于 {{min}} | | IntGe | IntGe:100 | “{{param}}”必须大于等于 {{min}} | | IntLt | IntLt:100 | “{{param}}”必须小于 {{max}} | | IntLe | IntLe:100 | “{{param}}”必须小于等于 {{max}} | | IntGtLt | IntGtLt:1,100 | “{{param}}”必须大于 {{min}} 小于 {{max}} | | IntGeLe | IntGeLe:1,100 | “{{param}}”必须大于等于 {{min}} 小于等于 {{max}} | | IntGtLe | IntGtLe:1,100 | “{{param}}”必须大于 {{min}} 小于等于 {{max}} | | IntGeLt | IntGeLt:1,100 | “{{param}}”必须大于等于 {{min}} 小于 {{max}} | | IntIn | IntIn:2,3,5,7,11 | “{{param}}”只能取这些值: {{valueList}} | | IntNotIn | IntNotIn:2,3,5,7,11 | “{{param}}”不能取这些值: {{valueList}} |

    A.2 浮点型

    内部一律使用double来处理

    | 浮点型验证器 | 示例 | 说明 | | :------| :------ | :------ | | Float | Float | “{{param}}”必须是浮点数 | | FloatGt | FloatGt:1.0 | “{{param}}”必须大于 {{min}} | | FloatGe | FloatGe:1.0 | “{{param}}”必须大于等于 {{min}} | | FloatLt | FloatLt:1.0 | “{{param}}”必须小于 {{max}} | | FloatLe | FloatLe:1.0 | “{{param}}”必须小于等于 {{max}} | | FloatGtLt | FloatGtLt:0,1.0 | “{{param}}”必须大于 {{min}} 小于 {{max}} | | FloatGeLe | FloatGeLe:0,1.0 | “{{param}}”必须大于等于 {{min}} 小于等于 {{max}} | | FloatGtLe | FloatGtLe:0,1.0 | “{{param}}”必须大于 {{min}} 小于等于 {{max}} | | FloatGeLt | FloatGeLt:0,1.0 | “{{param}}”必须大于等于 {{min}} 小于 {{max}} |

    A.3 bool型

    | bool型验证器 | 示例 | 说明 | | :------| :------ | :------ | | Bool | Bool | 合法的取值为: true, false, "true", "false"(忽略大小写) | | BoolSmart | BoolSmart | 合法的取值为: true, false, "true", "false", 1, 0, "1", "0", "yes", "no", "y", "n"(忽略大小写) |

    A.4 字符串型

    | 字符串型验证器 | 示例 | 说明 | | :------| :------ | :------ | | Str | Str | “{{param}}”必须是字符串 | | StrEq | StrEq:abc | “{{param}}”必须等于"{{value}}" | | StrEqI | StrEqI:abc | “{{param}}”必须等于"{{value}}"(忽略大小写) | | StrNe | StrNe:abc | “{{param}}”不能等于"{{value}}" | | StrNeI | StrNeI:abc | “{{param}}”不能等于"{{value}}"(忽略大小写) | | StrIn | StrIn:abc,def,g | “{{param}}”只能取这些值: {{valueList}} | | StrInI | StrInI:abc,def,g | “{{param}}”只能取这些值: {{valueList}}(忽略大小写) | | StrNotIn | StrNotIn:abc,def,g | “{{param}}”不能取这些值: {{valueList}} | | StrNotInI | StrNotInI:abc,def,g | “{{param}}”不能取这些值: {{valueList}}(忽略大小写) | | StrLen | StrLen:8 | “{{param}}”长度必须等于 {{length}} | | StrLenGe | StrLenGe:8 | “{{param}}”长度必须大于等于 {{min}} | | StrLenLe | StrLenLe:8 | “{{param}}”长度必须小于等于 {{max}} | | StrLenGeLe | StrLenGeLe:6,8 | “{{param}}”长度必须在 {{min}} - {{max}} 之间 | | ByteLen | ByteLen:8 | “{{param}}”长度(字节)必须等于 {{length}} | | ByteLenGe | ByteLenGe:8 | “{{param}}”长度(字节)必须大于等于 {{min}} | | ByteLenLe | ByteLenLe:8 | “{{param}}”长度(字节)必须小于等于 {{max}} | | ByteLenGeLe | ByteLenGeLe:6,8 | “{{param}}”长度(字节)必须在 {{min}} - {{max}} 之间 | | Letters | Letters | “{{param}}”只能包含字母 | | Alphabet | Alphabet | 同Letters | | Numbers | Numbers | “{{param}}”只能是纯数字 | | Digits | Digits | 同Numbers | | LettersNumbers | LettersNumbers | “{{param}}”只能包含字母和数字 | | Numeric | Numeric | “{{param}}”必须是数值。一般用于大数处理(超过double表示范围的数,一般会用字符串来表示)(尚未实现大数处理), 如果是正常范围内的数, 可以使用'Int'或'Float'来检测 | | VarName | VarName | “{{param}}”只能包含字母、数字和下划线,并且以字母或下划线开头 | | Email | Email | “{{param}}”必须是合法的email | | Url | Url | “{{param}}”必须是合法的Url地址 | | Ip | Ip | “{{param}}”必须是合法的IP地址 | | Mac | Mac | “{{param}}”必须是合法的MAC地址 | | Regexp | Regexp:/^abc$/ | Perl正则表达式匹配 |

    A.5 数组型

    | 数组型验证器 | 示例 | 说明 | | :------| :------ | :------ | | Arr | Arr | “{{param}}”必须是数组 | | ArrLen | ArrLen:5 | “{{param}}”数组长度必须等于 {{length}} | | ArrLenGe | ArrLenGe:1 | “{{param}}”数组长度必须大于等于 {{min}} | | ArrLenLe | ArrLenLe:9 | “{{param}}”数组长度必须小于等于 {{max}} | | ArrLenGeLe | ArrLenGeLe:1,9 | “{{param}}”长数组度必须在 {{min}} ~ {{max}} 之间 |

    A.6 对象型

    | 对象型验证器 | 示例 | 说明 | | :------| :------ | :------ | | Obj | Obj | “{{param}}”必须是对象 |

    A.7 文件型

    | 文件型验证器 | 示例 | 说明 | | :------| :------ | :------ | | File | File | “{{param}}”必须是文件 | | FileMaxSize | FileMaxSize:10mb | “{{param}}”必须是文件, 且文件大小不超过{{size}} | | FileMinSize | FileMinSize:100kb | “{{param}}”必须是文件, 且文件大小不小于{{size}} | | FileImage | FileImage | “{{param}}”必须是图片 | | FileVideo | FileVideo | “{{param}}”必须是视频文件 | | FileAudio | FileAudio | “{{param}}”必须是音频文件 | | FileMimes | FileMimes:mpeg,jpeg,png | “{{param}}”必须是这些MIME类型的文件:{{mimes}} |

    A.8 日期和时间型

    | 日期和时间型验证器 | 示例 | 说明 | | :------| :------ | :------ | | Date | Date | “{{param}}”必须符合日期格式YYYY-MM-DD | | DateFrom | DateFrom:2017-04-13 | “{{param}}”不得早于 {{from}} | | DateTo | DateTo:2017-04-13 | “{{param}}”不得晚于 {{to}} | | DateFromTo | DateFromTo:2017-04-13,2017-04-13 | “{{param}}”必须在 {{from}} ~ {{to}} 之间 | | DateTime | DateTime | “{{param}}”必须符合日期时间格式YYYY-MM-DD HH:mm:ss | | DateTimeFrom | DateTimeFrom:2017-04-13 12:00:00 | “{{param}}”不得早于 {{from}} | | DateTimeTo | DateTimeTo:2017-04-13 12:00:00 | “{{param}}”必须早于 {{to}} | | DateTimeFromTo | DateTimeFromTo:2017-04-13 12:00:00,2017-04-13 12:00:00 | “{{param}}”必须在 {{from}} ~ {{to}} 之间 |

    A.9 条件判断型

    在一条验证规则中,条件验证器必须在其它验证器前面,多个条件验证器可以串联。

    注意,条件判断中的“条件”一般是检测另外一个参数的值,而当前参数的值是由串联在条件判断验证器后面的其它验证器来验证。

    | 条件判断型验证器 | 示例 | 说明 | | :------| :------ | :------ | | If| If:selected | 如果参数"selected"值等于 1, true, '1', 'true', 'yes'或 'y'(字符串忽略大小写) | | IfNot| IfNot:selected | 如果参数"selected"值等于 0, false, '0', 'false', 'no'或'n'(字符串忽略大小写) | | IfTrue| IfTrue:selected | 如果参数"selected"值等于 true 或 'true'(忽略大小写) | | IfFalse| IfFalse:selected | 如果参数"selected"值等于 false 或 'false'(忽略大小写) | | IfExist| IfExist:var | 如果参数"var"存在 | | IfNotExist| IfNotExist:var | 如果参数"var"不存在 | | IfIntEq| IfIntEq:var,1 | if (var === 1) | | IfIntNe| IfIntNe:var,2 | if (var !== 2). 特别要注意的是如果条件参数var的数据类型不匹配, 那么If条件是成立的; 而其它几个IfIntXx当条件参数var的数据类型不匹配时, If条件不成立 | | IfIntGt| IfIntGt:var,0 | if (var > 0) | | IfIntLt| IfIntLt:var,1 | if (var < 0) | | IfIntGe| IfIntGe:var,6 | if (var >= 6) | | IfIntLe| IfIntLe:var,8 | if (var <= 8) | | IfIntIn| IfIntIn:var,2,3,5,7 | if (in_array(var, [2,3,5,7])) | | IfIntNotIn| IfIntNotIn:var,2,3,5,7 | if (!in_array(var, [2,3,5,7])) | | IfStrEq| IfStrEq:var,waiting | if (var === 'waiting') | | IfStrNe| IfStrNe:var,editing | if (var !== 'editing'). 特别要注意的是如果条件参数var的数据类型不匹配, 那么If条件是成立的; 而其它几个IfStrXx当条件参数var的数据类型不匹配时, If条件不成立 | | IfStrGt| IfStrGt:var,a | if (var > 'a') | | IfStrLt| IfStrLt:var,z | if (var < 'z') | | IfStrGe| IfStrGe:var,A | if (var >= '0') | | IfStrLe| IfStrLe:var,Z | if (var <= '9') | | IfStrIn| IfStrIn:var,normal,warning,error | if (in_array(var, ['normal', 'warning', 'error'], true)) | | IfStrNotIn| IfStrNotIn:var,warning,error | if (!in_array(var, ['warning', 'error'], true)) |

    A.10 其它验证器

    | 其它验证器 | 示例 | 说明 | | :------| :------ | :------ | | Required | Required | 待验证的参数是必需的。如果验证器串联,除了条件型验证器外,必须为第一个验证器 | | Alias | Alias:参数名称 | 自定义错误提示文本中的参数名称(必须是最后一个验证器) | | >>> | >>>:这是自定义错误提示文本 | 自定义错误提示文本(与Alias验证器二选一,必须是最后一个验证器) | | 自定义PHP函数 | function() {} | 暂不提供该机制,因为如果遇到本工具不支持的复杂参数验证,你可以直接写PHP代码来验证,不需要再经由本工具来验证(否则就是脱裤子放屁,多此一举) |WebGeeker-Validation: 一个强大的 PHP 参数验证器

    项目地址: github 码云

    用于对API接口的请求参数进行合法性检查。

    在实现服务端的API接口时,对于每一个接口的每一个参数,都应该检测其取值是否合法,以免错误的数据输入到系统中。这个工作可以说是费时费力,但又不得不做。而且PHP本身是弱类型语言,不但要验证取值,还要验证数据的类型是否符合,这就更复杂了。

    本工具就是针对这个工作而设计的,能够有效地减少编码量,代码可读性好。

    看看下面这段代码,可以对用法有个大概印象,应该不难看懂:

    $params = $request->query(); // 获取GET参数
    
    // 验证(如果验证不通过,会抛出异常)
    Validation::validate($params, [
        "offset" => "IntGe:0",
        "count" => "Required|IntGeLe:1,200",
    ]);
    

    支持多种数据类型的校验:整型、浮点型、bool型、字符串、数组、对象、文件、日期时间,能够验证嵌套的数据结构中的参数,还支持带条件判断的验证。

    • 目录
    • 1 简介
      • 1.1 为什么要写这样一个工具?
      • 1.2 特点
      • 1.3 一个简单示例
    • 2 安装
    • 3 快速上手
      • 3.1 一个完整的示例(不使用任何框架)
      • 3.2 验证不通过的错误处理
      • 3.3 在第三方框架中的用法
    • 4 详细使用方法
      • 4.1 验证整型参数
      • 4.2 验证浮点型参数
      • 4.3 验证bool型参数
      • 4.4 验证字符串型参数
      • 4.5 验证数组型、对象型、文件型、日期时间型参数
      • 4.6 验证器串联(与)
      • 4.7 Required 验证器
      • 4.8 忽略所有 Required 验证器
      • 4.9 嵌套参数的验证
      • 4.10 条件判断型验证器
      • 4.11 验证规则并联(或)
      • 4.12 关于特殊值null, "",0,false的问题
      • 4.13 关于基本数据类型与字符串的关系
      • 4.14 自定义错误信息输出文本
      • 4.15 国际化
      • 4.16 国际化(0.4版之前)
    • A 附录 - 验证器列表
      • A.1 整型
      • A.2 浮点型
      • A.3 bool型
      • A.4 字符串型
      • A.5 数组型
      • A.6 对象型
      • A.7 文件型
      • A.8 日期和时间型
      • A.9 条件判断型
      • A.10 其它验证器

    1 简介

    1.1 为什么要写这样一个工具?

    我在使用Laravel框架的时候,Laravel提供了一个参数验证工具,不过用起来不怎么顺畅: 每一个验证都写一个验证类(继承XXX),这样太麻烦,而且系统中会多出许多许多的类;如果这些类在多处被复用,或者为了“更加”复用(减少重复代码),再在这些类之间搞出很多的继承关系,那么这些类的维护本身就是一个大问题; 验证器有“一词多义”的问题。比如它有一个size验证器,它同时支持验证字符串、整型、文件等多种类型的参数,针对不同数据类型size的含义不一样。这就好比你去背英语单词,有那么一些英语单词,它有很多很多意思,不同的语境下有不同的含义。比如"present"这个单词,它既有“呈现”、“出席”的意思,也有“礼物”的意思。这种一词多义的单词最让人头疼了,搞不清它到底什么意思,而且记不住啊。

    为了解决这些问题,所以才写了这么一个工具。

    1.2 特点

    1. 简洁,验证逻辑一目了然(参考后面的例子)
    2. 轻量,不需要定义和维护各种验证classes
    3. 验证器语义明确,没有“一词多义”的问题
    4. 支持正则表达式验证
    5. 支持条件验证
    6. 理论上能够支持验证无限嵌套的参数
    7. 易学易记。比如整型验证器都是以"Int"开头,浮点型验证器都是以"Float"开头,等等。唯一不符合这一规则的是字符串型验证器,它们一部分以"Str"开头的,但也有一部分不以"Str"开头,比如Regexp, Ip, Email, Url等。
    8. 不绑定任何一个框架,无任何依赖。你可以在任何一个框架中使用这个工具,就算你不使用框架,也可以使用本工具。
    9. 每个功能特性都有单元测试(共有 41 tests, 369 assertions)

    1.3 一个简单示例

    下面这个示例展示了一个查询获取用户投诉列表的Request参数的验证(用到了条件验证和针对嵌套数据结构的验证):

    //验证规则
    $validations = [
        "offset" => "IntGe:0", // 参数offset应该大于等于0
        "count" => "Required|IntGeLe:1,200", // 参数count是必需的且大于等于1小于等于200
        "type" => "IntIn:1,2", // 参数type可取值为: 1, 2
        "state" => [
            'IfIntEq:type,1|IntEq:0', // 如果type==1(批评建议),那么参数state只能是0
            'IfIntEq:type,2|IntIn:0,1,2', // 如果type==2(用户投诉),那么参数state可取值为: 1, 2, 3
        ],
        "search.keyword" => "StrLenGeLe:1,100", // search.keyword 应该是一个长度在[1, 100]之间的字符串
        "search.start_time" => "Date", // search.start_time 应该是一个包含合法日期的字符串
        "search.end_time" => "BoolSmart", // search.end_time 应该是一个包含合法日期的字符串
    ];
    
    // 待验证参数
    $params = [
        "offset" => 0, // 从第0条记录开始
        "count" => 10, // 最多返回10条记录
        "type" => 2, // 1-批评建议, 2-用户投诉
        "state" => 0, // 0-待处理, 1-处理中, 2-已处理
        "search" => [ // 搜索条件
            "keyword" => '硬件故障', // 关键字
            "start_time" => "2018-01-01", // 起始日期
            "end_time" => "2018-01-31", // 结束日期
        ],
    ];
    
    // 验证(如果验证不通过,会抛出异常)
    Validation::validate($params, $validations);
    

    2 安装

    通过Composer安装

    composer require webgeeker/validation:^0.4

    3 快速上手

    3.1 一个完整的示例(不使用任何框架)

    这个例子直接验证$_POST(POST表单)中的参数,展示了最基本的用法

    <?php
    include "vendor/autoload.php";
    
    use WebGeekerValidationValidation;
    
    try {
        Validation::validate($_POST, [
            "offset" => "IntGe:0", // 参数offset应该大于等于0
            "count" => "Required|IntGeLe:1,200", // 参数count是必需的且大于等于1小于等于200
        ]);
    } catch (Exception $e) {
        echo $e->getMessage();
    }
    

    注意:验证不通过会抛出异常,该异常中包含有错误描述信息

    3.2 验证不通过的错误处理

    如果验证不通过,Validation::validate(...)方法会抛出异常,建议在框架层面统一捕获这些异常,提取错误描述信息并返回给客户端。

    3.3 在第三方框架中的用法

    第三方框架一般会提供Request对象,可以取到GET, POST参数(以Laravel为例)

    //$params = $request->query(); // 获取GET参数
    $params = $request->request->all(); // 获取POST参数
    
    // 验证(如果验证不通过,会抛出异常)
    Validation::validate($params, [
        // 此处省略验证规则
    ]);
    

    4 详细使用方法

    4.1 验证整型参数

    整型验证器全部以"Int"开头,用于验证整型数值(如123)或整型字符串(如"123")。其它数据类型均不匹配。

    "size" => "IntGeLe:1,100"
    

    这条验证要求参数"size"是整数,并且大于等于1,小于等于100。

    完整的整型验证器的列表参考附录 A.1 。

    4.2 验证浮点型参数

    浮点型验证器全部以"Float"开头,用于验证浮点型数值(如1.0)、浮点型字符串(如"1.0")、整型数值(如123)或整型字符串(如"123")。其它数据类型均不匹配。

    "height" => "FloatGeLe:0.0,100.0"
    

    这条验证要求参数"height"是浮点数,并且大于等于0,小于等于100.0。

    完整的浮点型验证器的列表参考附录 A.2 。

    4.3 验证bool型参数

    bool型验证器只有两个: Bool: 合法的取值为: true, false, "true", "false"(字符串忽略大小写)。 BoolSmart: 合法的取值为: true, false, "true", "false", 1, 0, "1", "0", "yes", "no", "y", "n"(字符串忽略大小写)

    "accept" => "BoolSmart"
    

    完整的bool型验证器的列表参考附录 A.3 。

    4.4 验证字符串型参数

    字符串型验证器不全以"Str"开头。只接收字符串型数据,其它数据类型均不匹配。

    例1:

    "name" => "StrLenGeLe:2,20"
    

    这条验证要求参数"name"是字符串,长度在2-20之间(字符串长度是用mb_strlen()来计算的)。

    例2:

    "comment" => "ByteLenLe:1048576"
    

    这条验证要求参数"comment"是字符串,字节长度不超过1048576(字节长度是用strlen()来计算的)。

    例3:

    "email" => "Email"
    

    这条验证要求参数"email"是必须是合法的电子邮件地址。

    例4(正则表达式验证):

    "phone" => "Regexp:/^1(3[0-9]|4[579]|5[0-35-9]|7[0135678]|8[0-9]|66|9[89])d{8}$/"
    

    这条验证要求参数"phone"是合法的手机号。

    关于正则表达式中的哪些特殊字符需要转义的问题,只需要用 preg_match() 函数验证好,如:

    preg_match('/^string$/', $string);

    然后把两个'/'号及其中间的部分拷贝出来,放在Regexp:后面即可,不需要再做额外的转义,即使正则中有'|'这种特殊符号,也不需要再转义。

    完整的字符串型验证器的列表参考附录 A.4 。

    4.5 验证数组型、对象型、文件型、日期时间型参数

    参考附录A.5-A.8

    4.6 验证器串联(与)

    一条规则中可以有多个验证器前后串联,它们之间是“AND”的关系,如:

    "file" => "FileMaxSize:10m|FileImage"
    

    这个验证要求参数"file"是一个图像文件,并且文件大小不超过10m

    4.7 Required 验证器

    • Required验证器要求参数必须存在,且其值不能为null(这个是PHP的null值,而不是字符串"null")(参数值为null等价于参数不存在)。
    • 如果多个验证器串联,Required验证器必须在其它验证器前面。
    • 如果还有条件验证器,Required必须串联在条件验证器后面。
    • 如果验证规则中没有 Required,当参数存在时才进行验证,验证不通过会抛异常;如果参数不存在,那么就不验证(相当于验证通过)

    例:

    "size" => "Required|StrIn:small,middle,large"
    

    该验证要求参数"size"必须是字符串的"small", "middle"或者"large"。

    4.8 忽略所有 Required 验证器

    比如当创建一个用户时,要求姓名、性别、年龄全部都要提供;但是当更新用户信息时,不需要提供全部信息,提供哪个信息就更新哪个信息。

    $validations = [
        "name" => "Required|StrLenGeLe:2,20",
        "sex" => "Required|IntIn:0,1",
        "age" => "Required|IntGeLe:1,200",
    ];
    
    $userInfo = [
        "name" => "tom",
        "sex" => "0",
        "age" => "10",
    ];
    Validation::validate($userInfo, $validations); // 创建用户时的验证
    
    unset($userInfo["age"]); // 删除age字段
    Validation::validate($userInfo, $validations, true); // 更新用户信息时的验证
    

    注意上面代码的最后一行:validate()函数的第三个参数为true表示忽略所有的 Required 验证器。

    这样我们就只需要写一份验证规则,就可以同时用于创建用户和更新用户信息这两个接口。

    4.9 嵌套参数的验证

    下面这个例子展示了包含数组和对象的嵌套的参数的验证:

    $params = [
        "comments" => [
            [
                "title" => "title 1",
                "content" => "content 1",
            ],
            [
                "title" => "title 1",
                "content" => "content 1",
            ],
            [
                "title" => "title 1",
                "content" => "content 1",
            ],
        ]
    ];
    
    $validations = [
        "comments[*].title" => "Required|StrLenGeLe:2,50",
        "comments[*].content" => "Required|StrLenGeLe:2,500",
    ];
    
    Validation::validate($params, $validations);
    

    4.10 条件判断型验证器

    条件判断型验证器都以"If"开头。

    比如你想招聘一批模特,男的要求180以上,女的要求170以上,验证可以这样写:

    $validations = [
        "sex" => "StrIn:male,female",
        "height" => [
            "IfStrEq:sex,male|IntGe:180",
            "IfStrEq:sex,female|IntGe:170",
        ],
    ];
    

    参数"sex"的值不同,参数"height"的验证规则也不一样。

    完整的条件判断型验证器的列表参考附录 A.9 。

    4.11 验证规则并联(或)

    多条验证规则可以并联,它们之间是“或”的关系,如

    "type" => [
        "StrIn:small,middle,large",
        "IntIn:1,2,3",
    ]
    

    上面这条验证要求参数"type"既可以是字符串"small", "middle"或"large",也可以整型的1, 2或3

    验证规则并联不是简单的“或”的关系,具体验证流程如下: 1. 按顺序验证这些规则,如果有一条验证规则通过, 则该参数验证通过。 2. 如果全部验证规则都被忽略(If验证器条件不满足,或者没有Required验证器并且该参数不存在,或者有0条验证规则),也算参数验证通过。 3. 上面两条都不满足, 则该参数验证失败。

    这些规则如果要完全理清并不是一件容易的事,所以不建议使用验证规则并联,也尽量不要设计需要这种验证方式的参数。

    4.12 关于特殊值null, ""0false的问题

    这些特殊的值是不等价的,它们是不同的数据类型(需要用不同的验证器去验证): ""是字符串。 0是整型。 false是bool型。 null是PHP的空。在本工具中它有特殊的含义。

    如果某个参数的值为null,则本工具会视为该参数不存在。

    比如下面两个array对于本工具来说是等价的.

    $params = [
        "name" => "hello",
    ];
    

    $params = [
        "name" => "hello",
        "comment" => null,
    ];
    

    是等价的。

    4.13 关于基本数据类型与字符串的关系

    对于以下url地址

    http://abc.com/index.php?p1=&&p2=hello&&p3=123

    我们将得到的参数数组:

    $params = [
        "p1" => "",
        "p2" => "hello",
        "p3" => "123",
    ];
    

    注意 参数"p1"的值为空字符串"",而不是null 参数"p3"的值为字符串"123",而不是整型123。 * GET方式的HTTP请求是传递不了null值的。

    本工具的所有验证器都是强类型的,"Int"验证的是整型,"Float"验证的是浮点型,"Str*"验证的是字符串型,数据类型不匹配,验证是通不过的。但是字符串类型是个例外。

    因为常规的HTTP请求,所有的基本数据类型最终都会转换成字符串,所以: 整型123和字符串"123"均可以通过验证器"Int"的验证; 浮点型123.0和字符串"123.0"均可以通过验证器"Float"的验证; bool型true和字符串"true"均可以通过验证器"Bool"的验证; 但是null值和字符串"null"永远不等价,字符串"null"就只是普通的字符串。

    4.14 自定义错误信息输出文本

    如果参数验证不通过,Validation::validate()方法会抛出异常,这个异常会包含验证不通过的错误信息描述的文本。

    但是这个描述文本对用户来说可能不那么友好,我们可以通过两个伪验证器来自定义这些文本: Alias 用于自定义参数名称(这个名称会与内部的错误信息模版相结合,生成最终的错误信息描述文本) >>> 用于自定义错误描述文本(这个文本会完全取代模版生成的错误描述文本)。

    看下面的例子:

    $params = [
        "title" => "a",
    ];
    
    Validation::validate($params, [
        "title" => "Required|StrLenGeLe:2,50",
    ]); // 抛出异常的错误描述为:“title”长度必须在 2 - 50 之间
    
    Validation::validate($params, [
        "title" => "Required|StrLenGeLe:2,50|Alias:标题", // 自定义参数名称
    ]); // 抛出异常的错误描述为:“标题”长度必须在 2 - 50 之间
    
    Validation::validate($params, [
        "title" => "Required|StrLenGeLe:2,50|>>>:标题长度应在2~50之间", // 自定义错误信息描述文本
    ]); // 抛出异常的错误描述为:标题长度应在2~50之间
    

    参考附录A.10获取更详细的信息

    4.15 国际化

    从0.4版开始: 使用新的静态成员变量 $langCode2ErrorTemplates 来进行“错误提示信息模版”的翻译,主要目的是简化格式(感谢 @gitHusband 的建议)。 旧的翻译表 $langCodeToErrorTemplates 仍然有效,已有代码无需修改(参考下一节)。如果新旧翻译表同时提供,优先新的,新表中查不到再使用旧的。

    要支持国际化,需要自定义一个类,继承WebGeekerValidationValidation,重载两个静态成员变量: $langCode2ErrorTemplates用于提供“错误提示信息模版”的翻译对照表。完整的错误提示信息模版列表可以在WebGeekerValidationValidation::$errorTemplates成员变量中找到 $langCodeToTranslations用于提供“自定义参数名称”(由Alias指定)和“自定义错误描述文本”(由>>>指定)的翻译对照表。

    下面提供一个示例类:

    class MyValidation extends Validation
    {
        // “错误提示信息模版”翻译对照表
        protected static $langCodeToErrorTemplates = [
            "zh-tw" => [
                'Int' => '“{{param}}”必須是整數', //  
                'IntGt' => '“{{param}}”必須大於 {{min}}',
                'Str' => '“{{param}}”必須是字符串',
            ],
            "en-us" => [
                'Int' => '{{param}} must be an integer',
                'IntGt' => '{{param}} must be greater than {{min}}',
                'Str' => '{{param}} must be a string',
            ],
        ];
    
        // 文本翻译对照表
        protected static $langCodeToTranslations = [
            "zh-tw" => [
                "变量" => "變量", //  
                "变量必须是整数" => "變量必須是整數", // ⭐
            ],
            "en-us" => [
                "变量" => "variable",
                "变量必须是整数" => "variable must be an integer",
            ],
        ];
    }
    

    注意: 语言代码是区分大小写的,建议全部用小写,如"zh-cn", "en-us"等。 语言代码的名称是自定义的,你可以随便起名,比如"abc"(建议使用标准的语言代码)。

    使用这个MyValidation类来进行验证,就可以实现文本的翻译了。

    MyValidation::setLangCode("zh-tw"); // 设置语言代码
    
    MyValidation::validate(["var" => 1.0], [
        "var" => "Int", // 既没有Alias,也没有>>>,只会翻译错误提示信息模版(对应 那行)
    ]); // 会抛出异常:“var”必須是整數
    
    MyValidation::validate(["var" => 1.0], [
        "var" => "Int|Alias:变量", // 有Alias,除了翻译错误提示信息模版外,还会翻译参数名称(对应 那行)
    ]); // 会抛出异常:“變量”必須是整數
    
    MyValidation::validate(["var" => 1.0], [
        "var" => "Int|>>>:变量必须是整数", // 有>>>,会翻译自定义错误描述文本(对应⭐那行)
    ]); // 会抛出异常:變量必須是整數
    

    如果提供了错误的语言代码,或者没有找到翻译的文本,那么就不翻译,输出原始的文本。

    4.16 国际化(0.4版之前)

    (如果你使用的是0.4及之后的版本,建议使用新的国际化方案(参考上一节),更简洁一点)

    要支持国际化,需要自定义一个类,继承WebGeekerValidationValidation,重载两个静态成员变量: $langCodeToErrorTemplates用于提供“错误提示信息模版”的翻译对照表。完整的错误提示信息模版列表可以在WebGeekerValidationValidation::$errorTemplates成员变量中找到 $langCodeToTranslations用于提供“自定义参数名称”(由Alias指定)和“自定义错误描述文本”(由>>>指定)的翻译对照表。

    下面提供一个示例类:

    class MyValidation extends Validation
    {
        // “错误提示信息模版”翻译对照表
        protected static $langCodeToErrorTemplates = [
            "zh-tw" => [
                "“{{param}}”必须是整数" => "“{{param}}”必須是整數", //  
                "“{{param}}”必须是字符串" => "“{{param}}”必須是字符串",
            ],
            "en-us" => [
                "“{{param}}”必须是整数" => "{{param}} must be a integer",
                "“{{param}}”必须是字符串" => "{{param}} must be a string",
            ],
        ];
    
        // 文本翻译对照表
        protected static $langCodeToTranslations = [
            "zh-tw" => [
                "变量" => "變量", //  
                "变量必须是整数" => "變量必須是整數", // ⭐
            ],
            "en-us" => [
                "变量" => "variable",
                "变量必须是整数" => "variable must be an integer",
            ],
        ];
    }
    

    注意: 语言代码是区分大小写的,建议全部用小写,如"zh-cn", "en-us"等。 语言代码的名称是自定义的,你可以随便起名,比如"abc"(建议使用标准的语言代码)。

    使用这个MyValidation类来进行验证,就可以实现文本的翻译了。

    MyValidation::setLangCode("zh-tw"); // 设置语言代码
    
    MyValidation::validate(["var" => 1.0], [
        "var" => "Int", // 既没有Alias,也没有>>>,只会翻译错误提示信息模版(对应 那行)
    ]); // 会抛出异常:“var”必須是整數
    
    MyValidation::validate(["var" => 1.0], [
        "var" => "Int|Alias:变量", // 有Alias,除了翻译错误提示信息模版外,还会翻译参数名称(对应 那行)
    ]); // 会抛出异常:“變量”必須是整數
    
    MyValidation::validate(["var" => 1.0], [
        "var" => "Int|>>>:变量必须是整数", // 有>>>,会翻译自定义错误描述文本(对应⭐那行)
    ]); // 会抛出异常:變量必須是整數
    

    如果提供了错误的语言代码,或者没有找到翻译的文本,那么就不翻译,输出原始的文本。

    A 附录 - 验证器列表

    由于不能正常显示表格,请移步:github 码云

    展开全文
  • python函数的默认参数请勿定义可变类型经常会看到这样一句代码警告:Default argument value is mutable意思是告诉我们函数的定义中,使用可变类型做默认参数。那为什么会有这个警告呢?可变类型和可变类型可变...

    python函数的默认参数请勿定义可变类型

    经常会看到这样一句代码警告:

    Default argument value is mutable

    意思是告诉我们函数的定义中,使用可变类型做默认参数。

    那为什么会有这个警告呢?

    可变类型和不可变类型

    可变类型(mutable):列表,字典

    不可变类型(unmutable):数字,字符串,元组

    定义可变类型会有什么问题?

    def fun(a=[]):

    a.append(1)

    print(a)

    if __name__ == "__main__":

    fun()

    fun()

    >>> [1]

    [1, 1]

    可以发现,默认参数定义可变类型之后,在第二次乃至更多次地调用同一个函数时,默认参数仿佛失去了效果。

    此时,在需要重复调用同一个函数的场景中,就非常容易导致问题,并且该问题不易察觉。在debug的时候就会表现成明明没有参数传进来,但是函数参数会有值,并且执行了不应该执行的操作。

    导致的原因

    我的理解:

    我们定义的函数本身是一个function的实例化对象,每当我们进行函数的定义时,就是创建了一个function的实例化对象,而默认参数就是其属性。

    在没有传入参数,以默认参数形式调用,并且改变了函数对象的属性值时,改变的属性值被保存下来,当第二次调用同一个对象时,属性值已经发生了改变。

    type(fun)

    >>> function

    解决方法

    def fun(a=None):

    if a is None:

    a = []

    a.append(1)

    print(a)

    if __name__ == "__main__":

    fun()

    fun()

    >>> [1]

    [1]

    展开全文
  • 这两个self-invoking anonymous 自调匿名函数,用这类的方法,能强制使匿名函数成为表达式,把不合法变成合法。()对函数赋值,所以function($){}(window.jQuery) 就是指把window.jQuery 作为参数传给前面的...
    function(){}();
    (function(){})();
    这两个是self-invoking anonymous 自调匿名函数,用这类的方法,能强制使匿名函数成为表达式,把不合法变成合法。

    ()是对函数赋值,所以function($){}(window.jQuery) 就是指把window.jQuery 作为参数传给前面的匿名函数,也就是$.

    这样做的好处是,在这个匿名函数代码块里保证了$ 与 window.jQuery 是相等的,并且不影响外部其他程序对$的改变。

    转载于:https://www.cnblogs.com/Jeely/p/10714858.html

    展开全文
  • 一、接口说明文档环境准备:安装火狐安装插件: httprequesterhttps://addons.mozilla.org/en-US/firefox/addon/httprequester/接口返回码:接口返回code说明:'00' : 成功'01':用户已存在'02':参数不合法'03':参数...
  • 1. 调用方法ValidateUtil.validate(String json,Map,String[]> map,String suffix);...本来操作方法放在readme.txt里的,不过知道资源为什么只能上传一个文件,没办法了,只能这在这里了。。。
  • Kafka auto.offset.reset

    2019-06-05 22:51:14
    今天突然想起一个问题,Kafka的消费offset在程序重启后,是接着上次消费的地方继续消费的,那auto.offset.reset 这个参数到底是什么意思呢?? 分析 总结 只有当group 找合法的offset,才会启用auto.offset....
  • 3.20 “semantics of‘>’change in ANSI C”的警告是什么意思? 71 3.21 “无符号保护”和“值保护”规则的区别在哪里? 71 第4章 指针 74 基本的指针应用 74 4.1 指针到底有什么好处? 74 4.2 我想声明一个...
  • 3.20 “semantics of‘>’change in ANSI C”的警告是什么意思? 71 3.21 “无符号保护”和“值保护”规则的区别在哪里? 71 第4章 指针 74 基本的指针应用 74 4.1 指针到底有什么好处? 74 4.2 我想声明一个...
  • 你必须知道的495个C语言问题

    千次下载 热门讨论 2015-05-08 11:09:25
    3.20 “semanticsof‘’changeinANSIC”的警告是什么意思? 3.21 “无符号保护”和“值保护”规则的区别在哪里? 第4章 指针 基本的指针应用 4.1 指针到底有什么好处? 4.2 我想声明一个指针并为它分配...
  • 1.11 extern在函数声明中是什么意思? 1.12 关键字auto到底有什么用途? 类型定义(typedef)  1.13 对于用户定义类型,typedef和#define有什么区别? 1.14 我似乎能成功定义一个链表。我试过typedefstruct{...
  •  1.11 extern在函数声明中是什么意思? 1.12 关键字auto到底有什么用途? 类型定义(typedef) 1.13 对于用户定义类型,typedef和#define有什么区别? 1.14 我似乎能成功定义一个链表。我试过typedefstruct{...
  • 《你必须知道的495个C语言问题》

    热门讨论 2010-03-20 16:41:18
    3.20 “semantics of‘’change in ANSI C”的警告是什么意思? 42 3.21 “无符号保护”和“值保护”规则的区别在哪里? 42 第4章 指针 45 基本的指针应用 45 4.1 指针到底有什么好处? 45 4.2 我想声明...
  • 1.11 extern在函数声明中是什么意思? 6 1.12 关键字auto到底有什么用途? 7 类型定义(typedef) 7 1.13 对于用户定义类型,typedef 和#define有什么区别? 7 1.14 我似乎能成功定义一个链表。我试过...
  • 关于int main(int argc,char* argv[])

    千次阅读 2018-12-05 21:57:15
    看实验室的main函数,以及之前看到的一些代码里,主函数总是int main(int argc,char* argv[]),之前写一直都是int main(),知道这两个参数是什么意思,上百度查询,特记录如下:   主函数main中变量(int ...
  • o 2.4 extern 在函数声明中是什么意思? o 2.5 关键字 auto 到底有什么用途? o 2.6 我似乎能成功定义一个链表。我试过 typedef struct { char *item; NODEPTR next; } *NODEPTR; 但是编译器报了错误信息。难道...
  •  3.20 “semantics of‘’change in ANSI C”的警告是什么意思?  3.21 “无符号保护”和“值保护”规则的区别在哪里? 第4章 指针  基本的指针应用  4.1 指针到底有什么好处?  4.2 我想声明一个指针并为它...
  • 3.20 “semantics of‘’change in ANSI C”的警告是什么意思? 3.21 “无符号保护”和“值保护”规则的区别在哪里? 第4章 指针 基本的指针应用 4.1 指针到底有什么好处? 4.2 我想声明一个指针并为它分配一些空间...
  • 3.20 “semantics of‘’change in ANSI C”的警告是什么意思? 3.21 “无符号保护”和“值保护”规则的区别在哪里? 第4章 指针 基本的指针应用 4.1 指针到底有什么好处? 4.2 我想声明一个指针并为它分配一些空间...
  • spring学习日记(一)

    2019-03-27 17:38:27
    2.使用@BindingResult来接收校验的结果,如果有不合法参数,从中取出结果信息,然后返回给前端页面 3.什么是token token的意思是“令牌”,服务端生成的一串字符串,作为客户端进行请求的一个标识。 当用户第一...
  • Linux常用命令-1

    2010-12-31 07:32:00
    文件命名规则:1.出了/之外,所有的字符都合法2....大小写敏感命令格式:命令 -选项 参数说明:选项的意思可以理解为不同的操作方法,不同的设置,命令以什么方式呈现等等,参数说的简单点就是命令操作的对象,可以对
  • 你必须知道的495个C语言问题(PDF)

    热门讨论 2009-09-15 10:25:47
    1.4 extern 在函数声明中是什么意思? . . . . . . . . . . . . . . . . . 2 1.5 关键字auto 到底有什么用途? . . . . . . . . . . . . . . . . . . . 2 1.6 我似乎能成功定义一个链表。我试过typedef struct f ...

空空如也

空空如也

1 2 3 4
收藏数 67
精华内容 26
关键字:

参数不合法是什么意思