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

让人头痛的表单验证

  本文译自 Matt Stauffer系列文章 .

  只要你曾经在使用 Laravel 框架的过程中试图找到有关用户输入验证的最佳实践, 你就应该了解这是一个争论最多并且几乎没有达成共识的话题. 我们可以在控制器中进行验证, 可以在单独的一个服务层进行验证, 可以在模型中进行验证, 当然还可以在 Javascript 中进行验证 (这只是一个玩笑, 谁都知道不能只依赖于客户端的验证). 但是, 哪一种做法才是最佳的呢?

  Laravel 5.0 新引入的表单请求 (Form Request) 特性提供了集规范性 (差不多就是 “最佳实践” 的意思) 和便捷性 (这是比之前任何一种选择都更强大也更便捷的方式) 于一体的, 在 Laravel 中执行数据检查和验证的新手段.

说明: 本文中使用新的 view() 辅助方法代替了旧版本中的 View::make() .

Form Requests 使表单验证不再让人头痛

  Laravel 5.0 带来了 Form Requests, 这是一种特殊的类型, 用于在提交表单时进行数据的检查和验证. 每个 Form Request 类至少包含一个 rules() 方法, 这个方法返回一组验证规则. 除此之外还必须包含一个 authorize() 方法, 该方法返回一个布尔值, 代表是否允许用户执行本次请求.

  Laravel 会在解析 POST 路由之前自动把用户输入的信息传递给相应的表单请求, 因此我们的所有验证逻辑都可以移到独立于控制器和模型之外的 FormRequest 对象中.

开始实践: 快速创建一个 Laravel 5.0 项目

  如果你还没有创建好的 Laravel 5.0 项目, 用下面的命令创建一个:

$ composer create-project laravel/laravel myProject dev-develop --prefer-dist

1. 添加路由

// app/Http/routes.php
Route::get('/', 'FriendsController@getAddFriend');
Route::post('/', 'FriendsController@postAddFriend');

2. 创建控制器

//app/Http/Controllers/FriendsController:
namespace App\Http\Controllers;
use App\Http\Requests\FriendFormRequest;
use Illuminate\Routing\Controller;
use Response;
use View;
class FriendsController extends Controller
{
    public function getAddFriend()
    {
        return view('friends.add');
    }
    public function postAddFriend(FriendFormRequest $request)
    {
        return Response::make('Friend added!');
    }
}

3. 创建视图

<html>
<body>
    @foreach ($errors->all() as $error)
        <p class="error">{{ $error }}</p>
    @endforeach
    <form method="post">
        <label>First name</label><input name="first_name"><br>
        <label>Email address</label><input name="email_address"><br>
        <input type="submit">
    </form>
</body>
</html>

4. 创建 FormRequest

// app/http/requests/FriendFormRequest.php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
use Response;
class FriendFormRequest extends FormRequest
{
    public function rules()
    {
        return [
            'first_name' => 'required',
            'email_address' => 'required|email'
        ];
    }
    public function authorize()
    {
        // 只允许登陆用户
        // 返回 \Auth::check();
        // 允许所有用户登入
        return true;
    }
    // 可选: 重写基类方法
    public function forbiddenResponse()
    {
        // 这个是可选的, 当认证失败时返回自定义的 HTTP 响应. 
        // (框架默认的行为是带着错误信息返回到起始页面)
        // 可以返回 Response 实例, 视图, 重定向或其它信息
        return Response::make('Permission denied foo!', 403);
    }
    // 可选: 重写基类方法
    public function response()
    {
        /* 如果需要自定义在验证失败时的行为, 可以重写这个方法
           了解有关基类中这个方法的默认行为,可以查看:    https://github.com/laravel/framework/blob/master/src/Illuminate/Foundation/Http/FormRequest.php
        */
  }
}

  接下来, 用 php artisan serve 或者你自己喜欢的方式启动服务器. 提交表单, 你可以看到我们并没有往控制器中添加任何一行验证逻辑, 但是验证规则已经生效了.

其它用例

  如果对 “新增” 和 “编辑” 有不同的规则, 或者根据不同的输入进行不同的验证, 要怎么办呢? 这里有几个可以参考的例子, 虽然还不能确定这些就是 “最佳实践”:

采用分开的 form requests

  Laravel 并没有规定你不能对 “新增” 和 “编辑” 操作采用不同的 form request 类. 所以你可以创建一个包含所有规则的 FriendFormRequest 作为基类, 然后把它扩展为 addFriendFormRequest 和 editFriendFormRequest 两个子类, 每个子类都可以实现各自的默认行为.

采用条件判断逻辑

  rules() 作为一个方法而不是属性, 带来的好处就是你可以在方法中添加判断逻辑:

class UserFormRequest extends FormRequest
{
    protected $rules = [   
        'email_address' => 'required',
        'password' => 'required|min:8',
    ];
    public function rules()
    {
        $rules = $this->rules;
        // 根据不同的情况, 添加不同的验证规则
        if ($someTestVariableShowingThisIsLoginInsteadOfSignup)
        {
            $rules['password'] = 'min:8';
        }
        return $rules;
    }
}

也可以在 authorize 方法中添加逻辑, 比如:

class FriendFormRequest extends FormRequest
{
    public function authorize()
    {
        if ( ! Auth::check() )
        {
            return false;
        }
        $thingBeingEdited = Thing::find(Input::get('thingId'));
        // 如果是编辑操作, 或者当前用户不是对象创建者
        if ( ! $thingBeingEdited || $thingBeingEdited->owner != Auth::id()) {
            return false;
        }
        return true;
    }
}

自定义校验

  除了上面的方式, 如果需要对验证逻辑进行更深入的控制, 可以重写提供校验对象实例的方法. 下面是一个简单的实例, 后续会专门写一篇文章来解释:

class FriendFormRequest extends FormRequest
{
    public function validator(ValidationService $service)
    {
        $validator = $service->getValidator($this->input());
        // 可选: 通过新的 ->after() 方法来进行自定义
        $validator->after(function() use ($validator)) {
        // 在这里可以做更多更深入的校验
            $validator->errors()->add('field', 'new error);
        }
    }
}

ValidatesWhenResolved 接口

  后续还会有一篇有关 ValidatesWhenResolved 接口的文章, 不过那篇文章重点讨论的是对方法/路由等的校验. IOC 何时提供什么东西, 这个在 Laravel 5.0 版已经分离出一个单独的接口. 官方文档: https://github.com/illuminate/contracts/blob/master/Validation/ValidatesWhenResolved.php

其它可自定义的参数:

redirect:URI. redirectRoute : 校验失败时要重定向到的路由. redirectAction:. dontFlash : 重定向时不要传递的输入项的键 (默认值: [‘password’, ‘password_confirmation’]).

写在最后

  通过文本可以看到, Form Requests 对于简化表单请求的数据校验是非常强大和方便的. 如果你阅读本文觉得还不够, 可以观看关于 Form Request 的 这个视频 .

  本文写作时, Laravel 5.0 还未正式发布, 因此上述内容最终可能还会有修改, 或者作者遗漏了某些东西. 如果你有建议或者对文章内容的修正, 可以在 给译者发邮件 或者(在 Twitter 上直接联系原作者)[http://twitter.com/stauffermatt].

原文地址:http://www.tuicool.com/articles/3IVvYva

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值