55.重构提交回复

未匹配的标注

本节说明

  • 对应视频教程第 55 小节:Refactoring to Form Requests

本节内容

就现在而言,处理提交新回复的方法看上去仍然有点臃肿,所以在本节中,我们将它重构为一个方法,然后再进行调用。我们将使用 表单请求验证 来进行我们的重构。首先我们创建表单请求类:

$ php artisan make:request CreatePostRequest

修改内容如下:
forum\app\Http\Requests\CreatePostRequest.php

<?php namespace App\Http\Requests; use Illuminate\Foundation\Http\FormRequest; class CreatePostRequest extends FormRequest { /** * Determine if the user is authorized to make this request. * * @return bool */ public function authorize() { return true; } /** * Get the validation rules that apply to the request. * * @return array */ public function rules() { return [ 'body' => 'required|spamfree', ]; } } 

注:我们暂时让authorize()方法返回true,并且将验证规则放在了rules()方法中。

现在我们的代码可以进行如下修改:
forum\app\Http\Controllers\RepliesController.php

 . . public function store($channelId,Thread $thread,CreatePostRequest $request) { if(Gate::denies('create',new Reply)) { return response( 'You are posting too frequently.Please take a break.:)',422 ); } $reply = $thread->addReply([ 'body' => request('body'), 'user_id' => auth()->id(), ]); return $reply = $thread->addReply([ 'body' => request('body'), 'user_id' => auth()->id(), ])->load('owner'); } . .

我们需要修改测试:
forum\tests\Feature\ParticipateInForumTest.php

 . . /** @test */ public function replies_that_contain_spam_may_not_be_created() { $this->withExceptionHandling(); $this->signIn(); $thread = create('App\Thread'); $reply = make('App\Reply',[ 'body' => 'something forbidden' ]); $this->post($thread->path() . '/replies',$reply->toArray()) ->assertStatus(422); } . .

运行测试:
file
我们需要对异常进行处理:
forum\app\Exceptions\Handler.php

 . . public function render($request, Exception $exception) { if($exception instanceof ValidationException){ return response('Validation failed.',422); } return parent::render($request, $exception); } . .

如果是ValidationException异常,我们返回 422。因为我们已经对异常进行了处理,再次运行测试:
file
接下来我们来整理我们的授权策略:
forum\app\Http\Requests\CreatePostRequest.php

<?php namespace App\Http\Requests; use App\Exceptions\ThrottleException; use Illuminate\Foundation\Http\FormRequest; use Illuminate\Support\Facades\Gate; class CreatePostRequest extends FormRequest { /** * Determine if the user is authorized to make this request. * * @return bool */ public function authorize() { return Gate::allows('create',new \App\Reply); } protected function failedAuthorization() { throw new ThrottleException; } /** * Get the validation rules that apply to the request. * * @return array */ public function rules() { return [ 'body' => 'required|spamfree', ]; } }

我们重写failedAuthorization(),并且定义了一个异常类:ThrottleException。这个异常类现在还没有建立,我们前往建立:
forum\app\Exceptions\ThrottleException.php

<?php namespace App\Exceptions; class ThrottleException extends \Exception { }

同样地,我们要为这个异常类做处理:
forum\app\Exceptions\Handler.php

 . . public function render($request, Exception $exception) { if($exception instanceof ValidationException){ return response('Validation failed.',422); } if($exception instanceof ThrottleException){ return response('You are posting too frequently.',429); } return parent::render($request, $exception); } . .

既然我们已经将授权策略转移了位置,那么我们的控制器代码就可以进行修改了:
forum\app\Http\Controllers\RepliesController.php

 . . public function store($channelId, Thread $thread, CreatePostRequest $request) { return $reply = $thread->addReply([ 'body' => request('body'), 'user_id' => auth()->id(), ])->load('owner'); } . .

我们还需要修改我们的测试:
forum\tests\Feature\ParticipateInForumTest.php

 . . /** @test */ public function users_may_only_reply_a_maximum_of_once_per_minute() { $this->withExceptionHandling(); $this->signIn(); $thread = create('App\Thread'); $reply = make('App\Reply',[ 'body' => 'My simple reply.' ]); $this->post($thread->path() . '/replies',$reply->toArray()) ->assertStatus(200); $this->post($thread->path() . '/replies',$reply->toArray()) ->assertStatus(429); } } . .

如果你观察得足够仔细,你会发现对授权策略的状态码返回,我们本节用的是 429,而上一节用的是 422。这是上一节我们的一个小错误,我们在本节进行修正。如果我们不清楚状态码的具体含义,我们可以在下面的文件中去确认状态码,例如我们现在需要的状态码 429,表示的是 HTTP_TOO_MANY_REQUESTS:
forum\vendor\symfony\http-foundation\Response.php

现在我们来运行全部测试:
file
我们的测试已经通过,但是如果你新建一个不合法的话题:
file
这是因为我们直接抛出了异常,而没有区分应用场合。我们进行下修改:
forum\app\Exceptions\Handler.php

 . . public function render($request, Exception $exception) { if($exception instanceof ValidationException){ if ($request->expectsJson()){ return response('Validation failed.',422); } } if($exception instanceof ThrottleException){ return response('You are posting too frequently.',429); } return parent::render($request, $exception); } . .

如果是Ajax调用,我们直接抛出异常;否则,我们不做处理。我们再次尝试:
file
我们再次运行全部测试:
file
修复未通过的测试:

 . . /** @test */ public function replies_that_contain_spam_may_not_be_created() { $this->withExceptionHandling(); $this->signIn(); $thread = create('App\Thread'); $reply = make('App\Reply',[ 'body' => 'something forbidden' ]); $this->json('post',$thread->path() . '/replies',$reply->toArray()) ->assertStatus(422); } . .

再次运行全部测试:
file

本文章首发在 LearnKu.com 网站上。

上一篇 下一篇
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
讨论数量: 0
发起讨论 只看当前版本


暂无话题~