$request->validate()源码解读

:confused:作为一个新手,看laravel官方文档时,总会想去看看源码是怎么实现的。

在看到表单验证那一块时,很好奇Request类调用validate方法与Validator::make()有什么区别?

Validator::make()倒是一下子看懂了,其实这只是调用了个外观类,但$request->validate()就有点看不懂了……

先去Request文件看看

发现只写了几个注释
@method array validate(array $rules, …$params)
并没有相应的方法,去它的父类里看发现也没有

魔法方法__call()

这种时候就想到了__call() 可以调用非本类中的方法,一找发现还是没有。
很纳闷,用反射类获取Request类的所有方法getMethods(),发现是有__call()的。
有点懵逼,遂发现Request用了几个Traits,主意查看,发现其中的Macroable是有__call()的

Macroable的__call()

那么$request调用validate()一定是通过这个__call()的。看看里面写了啥。
发现这个方法非常简单,就是看静态数组$macros中是否包含相应方法,有就调用。
那么问题来了,$macros数组中的方法是哪里来的 :sob:laravel真的好绕

FoundationServiceProvider

Kernel在进行handle()处理请求时,会先进行bootstrap阶段,这时会加载config/app中的provider,FoundationServiceProvider就是其中一个。它在register()阶段,执行了registerRequestValidation()方法。

registerRequestValidation()

给静态数组$macros注册validate、validateWithBag方法

源码:

file
// validator() 是在helper.php中
file
生成一个ValidationFactory(Illuminate\Contracts\Validation\Factory)的实例,并将该实例的validate方法注册到$macros数组中。
但是注意,这个Illuminate\Contracts\Validation\Factory是一个接口类,一定在什么地方已经和一个具体类进行了绑定~ :speak_no_evil:

注意: 一般框架自带的工具类,都会将简称和相应类名放在别名数组中。知道是为什么吗?

在Illuminate\Foundation\Application的构造函数中,有一个registerCoreContainerAliases()方法,它里面将一些简称和相应的类名关联起来,放到aliases数组和abstractAliases数组中

file

做这些aliases数组和abstractAliases数组的目的呢,我之前没想明白,现在明白了 就是在遇到像上面要实例化Illuminate\Contracts\Validation\Factory接口类时,自动做转换,转换为validator(而validator的绑定会在相应的provider中做掉)

结论

再来看看手动生成验证器

Validator::make()呢其实就是通过Facade来操作实例

file
巧了,也是validator!说明手动生成验证器和使用$request->validate() 其实调用的方法是一样的。

Validator这种外观类是怎么实现的,我这里就不说了,社区里一篇帖子分享一下
博客:深入浅出 Laravel 的 Facade 外观系统

最后找找validator绑定的具体类

在config/app的providers中查找,发现是在Illuminate\Validation\ValidationServiceProvider中register()时绑定了validator

file
绑定的类是Illuminate\Validation\Factory

一开始看laravel源码真的很痛苦,不过看多了会发现套路都差不多,努力学习!

本作品采用《CC 协议》,转载必须注明作者和本文链接
《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
讨论数量: 2

厉害了!
还想问下,$request->validate()验证后,如果多个参数验证没通过,返回的message会有“(and 1 more error)” 这个额外描述,这个应该怎么优雅地去除呢?

5个月前 评论

$request->validate() 能自定义验证规则对应的错误提示吗,params 根本不知道该传什么...

4个月前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!
未填写
文章
1
粉丝
0
喜欢
8
收藏
5
排名:2396
访问:551
私信
所有博文
社区赞助商