首页 » 工作 » 方法 » 正文

$request->validate () 和 $this->validate () 有什么区别?[转]

发布者:站点默认
2020/10/9 浏览数(49) 分类:方法 $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('表单验证通过');
}

解答

我和楼主有一样的问题,于是我去看了下源码

先去 Request 文件

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

魔法方法__call ()

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

Macroable 的__call ()

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

FoundationServiceProvider

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

registerRequestValidation()

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

源码:

//validator () 是在 helper.php 中

生成一个 ValidationFactory (Illuminate\Contracts\Validation\Factory) 的实例,并将该实例的 validate 方法注册到 $macros 数组中。

但是注意,这个 Illuminate\Contracts\Validation\Factory 是一个接口类,一定在什么地方已经和一个具体类进行了绑定~

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

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

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

结论

再来看看手动生成验证器

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

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

最后找找 validator 绑定的具体类

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

绑定的类是 Illuminate\Validation\Factory

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

转自:https://learnku.com/laravel/t/35039

点击返回顶部
  1. 留言
  2. 联系方式