$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('表单验证通过');
}
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
最佳答案

: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方法

源码:

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绑定的具体类

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

file 绑定的类是Illuminate\Validation\Factory

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

3年前 评论
讨论数量: 3

: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方法

源码:

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绑定的具体类

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

file 绑定的类是Illuminate\Validation\Factory

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

3年前 评论

我的理解是 验证请求过来数据是否合法。一个是保存数据是否合法。个人理解

4年前 评论

没区别,表现形式的不同而已。基于FormReuqest的验证更简洁,可以从构造函数中提取出去。本质上应该也是 Facades 的表现形式

4年前 评论

: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方法

源码:

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绑定的具体类

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

file 绑定的类是Illuminate\Validation\Factory

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

3年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!