$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 协议》,转载必须注明作者和本文链接
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
讨论数量: 2

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

5个月前 评论

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

4个月前 评论

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