[译]Laravel 5.0 之 ValidatesWhenResolved

本文译自 Matt Stauffer 的系列文章.


在创建 FormRequest 的时候, Taylor(译注: Laravel 框架的作者) 还编写了一个接口 (ValidatesWhenResolved) 和一个 trait (ValidatesWhenResolvedTrait), 都是用于对控制器方法进行校验的. 这种校验会在IOC 容器对该方法的依赖项解析成功时调用.

老实说, 我目前还没有写出一个在 FormRequests 类之外的应用场景来使用这两个东西的实例. 但我还是想写一篇文档来介绍它们, 希望有比我更聪明的人来找出它们在实际项目中可能的应用场景.

所以, 如果你读过我的上一篇文章, 你已经了解了 FormRequest 对象, 通过 IOC 的依赖注入机制注入到方法, 可以取消相关方法的执行. 假如表单提交的数据不能通过校验, 与该表单对应的 POST route 会被负责校验它的 FormRequest 类取消执行.

这带来的一个结果就是: "触发 IOC 容器的 FormRequest 调用校验方法" 这个操作可以被分离为一个单独的接口, 名为 ValidatesWhenResolved. 借助这一点, 我们也可以创建类似 FormRequest 的类, 在执行控制器方法 (理论上非控制器也可以) 之前对请求进行拦截, 并决定它能否通过校验.

说明: 如果一个请求校验失败的话, 路由或方法其实没有真正取消. FormRequest 只是抛出了一个 HTTP 异常, 该异常随后以 JSON 格式返回, 或者被重定向到处理异常的页面. 理论上来说, 你不实现这个接口, 而只是简单地在控制器的构造函数中进行校验并抛出异常也是一样的. 但是借助这个接口, 我们可以保持代码清洁, 并且可以在一个命名的方法中来执行校验.

接口

在本文写作的时候, 该接口的签名是这样的:

namespace Illuminate\Contracts\Validation;

use Illuminate\Contracts\Container\Container;

interface ValidatesWhenResolved {

    /**
     * 对指定的类实例进行校验
     *
     * @return void
     */
    public function validate();

}

通过该签名可知, 实现这个接口只需要实现一个方法 validate(). 事实上, 对于实现这个方法的类, 我们只需要知道一点, 就是当 IOC 容器解析到它的时候, 会调用 validate() 这个方法. 接下来我们就来创建一个并非 FormRequest 扩展类但是却实现了这个接口的类:

在控制器中不使用 FormRequest 进行校验

// app/Http/Controllers/ValidatedController.php

namespace App\Http\Controllers;

use App\Random\RandomAccess;
use Illuminate\Routing\Controller;
use Response;

class ValidatedController extends Controller
{
    public function random(RandomAccess $ram)
    {
        return Response::make('You made it!');
    }
}

上面是一个简单的控制器. 有了路由之后, 我们来创建一个不继承 FormRequest 的验证类:

// app/Random/RandomAccess.php
namespace App\Random;

use Exception;
use Illuminate\Contracts\Validation\ValidatesWhenResolved;
use Illuminate\Http\Request;

class RandomAccess implements ValidatesWhenResolved
{
    public function __construct(Request $request)
    {
        $this->request = $request;
    }

    public function validate()
    {
        // Test for an even vs. odd remote port
        if (($this->request->server->get('REMOTE_PORT') / 2) % 2 > 0)
        {
            throw new Exception("WE DON'T LIKE ODD REMOTE PORTS");
        }
    }
}

现在控制器方法就被拦截并且随机抛出异常 (取决于请求访问的端口是奇数还是偶数, 这恐怕是有史以来最没实用价值的一个例子了, 哈哈).

如你所见, 这里没有用到什么神奇的东西, validate() 方法是否返回 true 或者 false 并不重要. 你当然可以通过 ValidatesWhenResolvedTrait 这个 trait 来实现 FormRequest 中的 failedValidation() 的部分流程, 而在上面的例子中, 只需要抛出异常就可以了.

在控制器之外使用 FormRequest 风格的验证

在控制器之外也可以使用这些手段, 比如在 FormRequest 风格的验证中使用 ValidatesWhenResolvedTrait. 但我暂时没有找到合适的用例, 所以我先简单地略过这部分. 你可以自己尝试... 但是我想不出有什么理由值得这样去做, 呵呵.

真实案例

你肯定不会像上面的例子里那样去随机抛出异常. 本文探讨的这些新特性最终看起来有点像以前的 route filters. 但我还是怀疑它们在实际中能有多少应用场景. 不管怎么说, 要是你想给你的控制器注入什么东西的话, 或者可以让它实现 ValidatesWhenResolved 接口或者使用 ValidatesWhenResolvedTrait, 这样它就能通过注入进行自动校验, 不用额外去调用一个校验方法了.

结束语

你可以认为这篇文章的目的就是为了钓鱼, 看看能否找到对这个新特性的实际应用场景. 假如你有什么想法, 可以通过 Twitter 与 @stauffermatt 进行讨论.

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏编程

我是如何利用CSRF Get DedeCms Shell的

说实话,有一两个月没有审计大厂了,然后随便看到群里有人问dede最新有没有漏洞,就下了一套最新的dede,结果我一看还真发现了。 ? 我们发现后台添加广告的地方...

2187
来自专栏小李刀刀的专栏

[译]Laravel 5.0 之 表单验证类 (Form Requests)

本文译自 Matt Stauffer 的系列文章. ---- 让人头痛的表单验证 只要你曾经在使用 Laravel 框架的过程中试图找到有关用户输入验证的最佳实...

4575
来自专栏Kirito的技术分享

从Spring Session源码看Session机制的实现细节

去年我曾经写过几篇和 Spring Session 相关的文章,从一个未接触过 Spring Session 的初学者视角介绍了 Spring Session ...

64412
来自专栏腾讯云数据库团队的专栏

Hbase WAL 线程模型源码分析

Hbase的WAL机制是保证hbase使用lsm树存储模型把随机写转化成顺序写,并从内存read数据,从而提高大规模读写效率的关键一环。wal的多生产者单消费者...

6.2K3
来自专栏Kiba518

C#——Nhibernate探索

该版本可能是最新版,我下载的4.0.4.GA。其中GA意思我没搞清楚。不过应该不重要。

1163
来自专栏bboysoul

linux 终端下最简单的代理方式(proxychains)

我以前写过给linux终端设置代理 这个是用polipo这个工具把socks5代理转换成为http和https代理来实现终端下代理的,那么终端下有没有原生的使...

2002
来自专栏FreeBuf

路由器漏洞分析第五弹:CVE-2018-5767远程代码执行

*本文作者:kczwa1,本文属 FreeBuf 原创奖励计划,未经许可禁止转载。

1582
来自专栏ml

c/c++----网站及其后门(CGI应用程序)

      C/C++学习到这儿,结合自己曾经学过的javasweb知识,现在让我们来看看,如何做一个CGI程序吧!       首先了解一下啥子叫CGI  :...

3524
来自专栏静晴轩

Gulp探究折腾之路(I)

前言: gulp是前端开发过程中对代码进行构建的工具,是自动化项目的构建利器;她不仅能对网站资源进行优化,而且在开发过程中很多重复的任务能够使用正确的工具自动完...

3758
来自专栏java思维导图

Java中高级面试题部分答案解析(4)

这里选了几道高频面试题以及一些解答。不一定全部正确,有一些是没有固定答案的,如果发现有错误的欢迎纠正,如果有更好的回答,热烈欢迎留言探讨。

1333

扫码关注云+社区

领取腾讯云代金券