资讯动态

Respect Validation 条件校验器 Given 深入解析:当条件成立时才校验,否则静默放行

发布时间:2026/10/6 2:06:46 来源:尧图企业网站定制
后端开发工具【免费下载链接】ValidationThe most awesome validation engine ever created for PHP项目地址https://gitcode.com/gh_mirrors/va/Validation点击查看免费下载Given(Validator $when, Validator $then)是 PHP 校验库 Respect\Validation 在 3.2.0 版本引入的条件型校验器只有当条件校验器$when对输入通过时才会继续执行$then校验条件不成立时直接静默放行不存在$else分支。本文将从官方文档出发结合 Given 源码 与测试用例讲解它的行为语义、与When的差异、在AllOf/ShortCircuit链中的最佳实践以及消息模板的自定义方式帮助你写出“跳过无关校验”的精准验证逻辑。一、核心语义条件成立才校验否则静默通过Given的签名在文档中定义为Given(Validator $when, Validator $then)其行为可以概括为一句话当$when对输入通过时返回$then的校验结果否则直接返回通过passes silently。文档给出的三个示例可以清晰展示这一语义v::given(v::intVal(), v::positive())-assert(5); // Validation passes successfully v::given(v::intVal(), v::positive())-assert(non-integer); // Validation passes successfully v::given(v::intVal(), v::positive())-assert(-1); // → -1 must be a positive number解读这三个分支输入5intVal()通过接着校验positive()通过输入non-integerintVal()不通过Given不执行positive()整体静默通过输入-1intVal()通过positive()失败抛出异常消息为-1 must be a positive number。文档特别强调如果$input不是整数校验静默通过——不存在$else分支。这一点与同为条件型校验器的 When 有本质区别详见下文第四节对比。二、源码级解读evaluate() 到底做了什么Given的实现非常精简完整源码位于 src/Validators/Given.php#[Attribute(Attribute::TARGET_PROPERTY | Attribute::TARGET_CLASS | Attribute::IS_REPEATABLE)] final readonly class Given implements Validator { public function __construct( private Validator $when, private Validator $then, ) { } public function evaluate(mixed $input): Result { if ($this-when-evaluate($input)-hasPassed) { return $this-then-evaluate($input); } return (new AlwaysValid())-evaluate($input); } }从源码结构可以提炼出几个关键实现事实条件判定基于Result::hasPassedGiven调用$this-when-evaluate($input)仅以返回的Result对象上的hasPassed布尔值决定分支走向自身并不关心$when失败的具体原因。“静默通过”由AlwaysValid兜底实现当$when不通过时直接构造 AlwaysValid 并返回其求值结果。AlwaysValid::isValid()恒为true模板为{{subject}} must be valid因此对调用方而言条件未命中时Given表现如同一个恒真的占位校验器。构造函数只接受两个校验器没有第三个$else参数。这一点与When可传入$else默认 AlwaysInvalid形成对照——Given的“未命中即放行”行为是硬编码在类型结构里的。final readonly class PHP 8 属性Attribute与仓库中绝大多数校验器一致Given被声明为只读终类且带有#[Attribute(Attribute::TARGET_PROPERTY | Attribute::TARGET_CLASS | Attribute::IS_REPEATABLE)]意味着它既可以作为链式调用中的普通校验器也可以直接作为类属性注解使用。实现Validator接口Given直接实现 src/Validator.php 中定义的Validator接口仅需实现evaluate(mixed $input): Result因此它可以被嵌套进任何复合校验器如AllOf、ShortCircuit内部。同时仓库的 Builder/Chain 混入类也提供了同名工厂方法见 src/Mixins/Builder.php 与 src/Mixins/Chain.phppublic static function given(Validator $when, Validator $then): Chain; public function given(Validator $when, Validator $then): Chain;这意味着你既可以用静态入口v::given(...)也可以在任意链上继续-given(...)拼接后续校验器。三、为什么“静默放行”在 AllOf / ShortCircuit 链中特别有用文档明确指出“当跳过无关校验是期望行为时Given在AllOf或ShortCircuit链中非常理想”原文This makesGivenideal insideAllOforShortCircuitchains where skip when irrelevant is the desired behavior。理解这一点需要先看两种复合校验器的差异AllOf会求值所有子校验器并收集全部失败其evaluate()通过array_map逐个执行子校验器后聚合Result见 src/Validators/AllOf.php。ShortCircuit类似 PHP 的遇到第一个失败立即返回后续校验器不再执行见 src/Validators/ShortCircuit.php。Given的价值在于把它作为链中的一个节点时它可以按输入动态地“启用/禁用”某条校验规则而不破坏链的整体结构。典型的组合写法如下$validator v::allOf( v::given(v::stringType(), v::length(3, 10)), // 只有字符串才检查长度 v::given(v::not(v::stringType()), v::alwaysValid()), // 非字符串直接跳过 ); $validator-assert(abc); // 通过 $validator-assert(toolong123); // 抛出长度校验失败 $validator-assert(12345); // 静默通过不是字符串长度规则被跳过在ShortCircuit中Given的“条件不成立返回通过”还能避免误触发出错短路——例如只有前置条件满足时才需要检查的字段条件不满足时让短路逻辑继续向后执行而不是把“跳过”误判为“失败”。四、Given 与 When 的对比有无 else 分支是关键差异Given常被拿来与 When 比较两者都是条件型校验器但语义不同维度Given(Validator $when, Validator $then)When(Validator $when, Validator $then[, Validator $else])条件通过校验$then校验$then条件不通过静默放行AlwaysValid校验$else未提供$else时默认使用AlwaysInvalid行为模型二分支无失败路径三分支恒有结果适用场景“不相关就跳过”严格的 if / else 分支对照 When 源码 可以看到When的构造器第三个参数默认值是new Templated(AlwaysInvalid::TEMPLATE_SIMPLE, new AlwaysInvalid())即条件不通过时默认失败而Given的构造器根本不存在第三个参数条件不通过时由AlwaysValid兜底通过。因此需要“不满足条件就报错”时用When需要“不满足条件就跳过、永不报错”时用Given。文档的 See Also 同时列出两者正是提示读者在二者之间按语义取舍。此外ShortCircuit 文档 还提到一个工程技巧与其在When中重复书写条件校验器不如用Given或ShortCircuitFactory避免重复——这是Given在真实项目中的另一大卖点。五、消息模板subject 占位符与自定义模板Given自身并不产生独立模板它的模板占位符只有一个占位符说明subject被校验的输入值若指定了自定义校验器名称则为该校验器名称实际抛出的消息完全来自内部$then校验器的模板。仓库的功能测试 tests/feature/Validators/GivenTest.php 验证了消息的三种形态默认消息v::given(v::intVal(), v::positive())-assert(-1); // message: -1 must be a positive number // fullMessage: - -1 must be a positive number // messages: [positive -1 must be a positive number]单一字符串模板替换整条消息v::given(v::intVal(), v::positive())-assert(-1, That did not go as planned); // message: That did not go as planned按校验器名分组的数组模板v::given(v::intVal(), v::positive())-assert(-1, [positive Not a positive number]); // message: Not a positive number可以看到自定义模板既可以按$then内部校验器的名称此处为positive定向替换也可以整体替换fullMessage与messages数组会同步反映替换结果。六、测试验证Given 的四象限行为矩阵单元测试 tests/unit/Validators/GivenTest.php 用Stub桩校验器把Given的四种组合全部覆盖// providerForValidInput应当通过 when fail, then daze [new Given(Stub::fail(1), Stub::daze()), rand()], when pass, then pass [new Given(Stub::pass(1), Stub::pass(1)), rand()], // providerForInvalidInput应当失败 when pass, then fail [new Given(Stub::pass(1), Stub::fail(1)), rand()],对应行为矩阵为$when结果$then结果Given整体结果失败任意daze桩通过静默放行通过通过通过通过失败失败返回$then的失败结果这组用例从行为层验证了文档对Given的描述唯一导致校验失败的情形是条件成立且$then校验失败其余三种情况均通过。七、分类与版本信息分类CategorizationConditions条件、Nesting嵌套。这意味着Given属于条件逻辑类校验器且设计上鼓励被嵌套进更复杂的组合结构中。版本历史Changelog3.2.0创建。它是在 Respect\Validation v3.2.0 中新增的校验器属于较新引入的 API。八、相关校验器一览Given与其他逻辑类校验器共同构成条件校验家族官方文档的 See Also 指向AllOf全部子校验器通过才通过会收集所有失败AlwaysValid恒真校验器Given静默放行路径的底层实现AnyOf任一子校验器通过即通过NoneOf所有子校验器都不通过才通过OneOf恰好一个子校验器通过才通过ShortCircuit短路求值遇首个失败即返回When带$else分支的三元条件校验器与Given形成互补。结语Given以最小的 API 面两个参数、无 else、静默放行解决了条件校验中最常见的一类需求——“与输入无关的规则就不要执行也不要报错”。无论是嵌在AllOf中按输入类型动态启用规则还是放进ShortCircuit避免无关失败提前短路它都能让校验逻辑更贴近业务语义。使用时的要点只有一条想清楚条件不成立时是“跳过”用Given还是“走 else 分支”用When——这正是文档与源码共同强调的核心分界线。赞分享后端开发工具【免费下载链接】ValidationThe most awesome validation engine ever created for PHP项目地址https://gitcode.com/gh_mirrors/va/Validation点击查看免费下载相关推荐class-validator 条件验证指南ValidateIf 实现指定条件下才执行校验的实用技巧class validator 条件验证指南ValidateIf 实现指定条件下才执行校验的实用技巧 在 TypeScript 项目中 class val后端开发工具Gradle 工作校验Work Validation机制全解静态校验与运行时校验的源码级剖析Gradle 工作校验Work Validation机制全解静态校验与运行时校验的源码级剖析 本文以 Work Validation.md 为核心骨架结构建工具开发工具Ant Design Form 动态校验规则实战让校验条件随状态实时变化Ant Design Form 动态校验规则实战让校验条件随状态实时变化 表单校验规则并非只能静态写死。在 Ant Design 中 Form.Item 的前端UI组件设计系统上一篇vue2-ace-editorVue 2.x 的终极代码编辑器解决方案下一篇WSA PacmanWindows上最直观的安卓应用管理神器终极指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑