$request->validate () 和 $this->validate () 有什么区别?
我的理解
$this->validate 是因为所有控制器都使用了 ValidatesRequests
Trait,所以可以使用这个 Trait 中提供的 validate()
方法
那 \App\Http\Requests 里的 validate() 方法是从哪里来的?最终实现是相同的吗?为什么会有两种写法?(我知道 Validator::make()
是为了在 控制器外边用)
Laravel 代码如下:
$request->validate()
protected function validateLogin(\App\Http\Requests $request)
{
$request->validate([ // <---- 看这行
'username' => 'required|string',
'password' => 'required|string',
'captcha' => ['required', 'captcha'],
], [
'captcha.required' => '验证码不能为空',
'captcha.captcha' => '请输入正确的验证码',
]);
}
$this->validate()
public function form(Request $request, $id)
{
$this->validate($request, [ // <---- 看这行
'title' => 'bail|required|string|between:2,32',
'url' => 'sometimes|url|max:200',
'picture' => 'nullable|string'
]);
return response('表单验证通过');
}
:confused:我和楼主有一样的问题,于是我去看了下源码
先去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方法
源码:
注意: 一般框架自带的工具类,都会将简称和相应类名放在别名数组中。知道是为什么吗?
在Illuminate\Foundation\Application的构造函数中,有一个registerCoreContainerAliases()方法,它里面将一些简称和相应的类名关联起来,放到aliases数组和abstractAliases数组中
做这些aliases数组和abstractAliases数组的目的呢,我之前没想明白,现在明白了
就是在遇到像上面要实例化Illuminate\Contracts\Validation\Factory接口类时,自动做转换,转换为validator(而validator的绑定会在相应的provider中做掉)结论
再来看看手动生成验证器
Validator::make()呢其实就是通过Facade来操作实例
最后找找validator绑定的具体类
在config/app的providers中查找,发现是在Illuminate\Validation\ValidationServiceProvider中register()时绑定了validator
一开始看laravel源码真的很痛苦,不过看多了会发现套路都差不多,努力学习!