31.删除回复
- 本系列文章为
laracasts.com
的系列视频教程——Let's Build A Forum with Laravel and TDD 的学习笔记。若喜欢该系列视频,可去该网站订阅后下载该系列视频, 支持正版 ;- 视频源码地址:github.com/laracasts/Lets-Build-a-...;
- 本项目为一个 forum(论坛)项目,与本站的第二本实战教程 《Laravel 教程 - Web 开发实战进阶》 类似,可互相参照。
本节说明
- 对应视频第 31 小节:Authorized Users Can Delete Replies
本节内容
本节我们完成删除回复的功能。首先新建测试:
forum\tests\Feature\ParticipateInForumTest.php
.
.
/** @test */
public function unauthorized_users_cannot_delete_replies()
{
$this->withExceptionHandling();
$reply = create('App\Reply');
$this->delete("/replies/{$reply->id}")
->assertRedirect('login');
}
}
接着建立路由:
forum\routes\web.php
.
.
Route::delete('/replies/{reply}','RepliesController@destroy');
Route::post('/replies/{reply}/favorites','FavoritesController@store');
.
虽然我们现在还没有destroy()
方法,但是如果我们运行测试,仍然会通过。因为我们使用了中间件$this->middleware('auth')
,未登录用户会直接被重定向至登录页面,所以我们的测试会通过:
现在我们已经测试了未登录用户,接下来加上已登录但无权限用户的测试:
.
.
/** @test */
public function unauthorized_users_cannot_delete_replies()
{
$this->withExceptionHandling();
$reply = create('App\Reply');
$this->delete("/replies/{$reply->id}")
->assertRedirect('login');
$this->signIn()
->delete("/replies/{$reply->id}")
->assertStatus(403);
}
}
添加destroy()
方法:
forum\app\Http\Controllers\RepliesController.php
<?php
namespace App\Http\Controllers;
use App\Reply;
use App\Thread;
class RepliesController extends Controller
{
public function __construct()
{
$this->middleware('auth');
}
public function store($channelId,Thread $thread)
{
$this->validate(request(),['body' => 'required']);
$thread->addReply([
'body' => request('body'),
'user_id' => auth()->id(),
]);
return back()->with('flash','Your reply has been left.');
}
public function destroy(Reply $reply)
{
if($reply->user_id != auth()->id()){
return response([],403);
}
$reply->delete();
return back();
}
}
运行测试:
现在我们来测试有权限的用户:
forum\tests\Feature\ParticipateInForumTest.php
.
.
/** @test */
public function authorized_users_can_delete_replies()
{
$this->signIn();
$reply = create('App\Reply',['user_id' => auth()->id()]);
$this->delete("/replies/{$reply->id}")->assertStatus(302);
$this->assertDatabaseMissing('replies',['id' => $reply->id]);
}
}
运行测试:
我们实际上测试了两个动作:删除跟重定向。现在测试代码已经编写完成,接下来让我们进行重构:使用Policy
来做权限控制。首先新建Policy
:
$ php artisan make:policy ReplyPolicy
forum\app\Policies\ReplyPolicy.php
<?php
namespace App\Policies;
use App\User;
use App\Reply;
use Illuminate\Auth\Access\HandlesAuthorization;
class ReplyPolicy
{
use HandlesAuthorization;
public function update(User $user, Reply $reply)
{
return $reply->user_id == $user->id;
}
}
注册Policy
:
forum\app\Providers\AuthServiceProvider.php
.
.
protected $policies = [
'App\Thread' => 'App\Policies\ThreadPolicy',
'App\Reply' => 'App\Policies\ReplyPolicy',
];
.
.
应用Policy
:
forum\app\Http\Controllers\RepliesController.php
.
.
public function destroy(Reply $reply)
{
$this->authorize('update',$reply);
$reply->delete();
return back();
}
}
运行全部测试:
我们还有最后一步要做,那就是在前端应用功能:
forum\resources\views\threads\reply.blade.php
.
.
@can('update',$reply)
<div class="panel-footer">
<form method="POST" action="/replies/{{ $reply->id }}">
{{ csrf_field() }}
{{ method_field('DELETE') }}
<button type="submit" class="btn btn-danger btn-xs">Delete</button>
</form>
</div>
@endcan
</div>