28.话题删除的 Bug

未匹配的标注

本节说明

  • 对应视频第 28 小节:The Activity Deletion Bug

本节内容

现在我们的系统存在一个 Bug,那就是如果我们创建了话题,然后再删除,然后访问个人页面的话就会出现 Bug。因为我们在动作流里试图关联一个被删除了的话题对象。我们来试一下。
首先创建一个话题:
file
查看个人页面:
file
删除该话题后再查看个人页面:
file
我们来修复这个 Bug。首先我们在删除话题的测试中增加相关测试代码:
forum\tests\Feature\CreateThreadsTest.php

.
.
/** @test */
public function authorized_users_can_delete_threads()
{
    $this->signIn();

    $thread = create('App\Thread',['user_id' => auth()->id()]);
    $reply = create('App\Reply',['thread_id' => $thread->id]);

    $response =  $this->json('DELETE',$thread->path());

    $response->assertStatus(204);

    $this->assertDatabaseMissing('threads',['id' => $thread->id]);
    $this->assertDatabaseMissing('replies',['id' => $reply->id]);

    $this->assertDatabaseMissing('activities',[
        'subject_id' => $thread->id,
        'subject_type' => get_class($thread)
    ]);
}
.
.

单独运行测试:
file
forum\app\RecordsActivity.php

.
.
trait RecordsActivity
{

    protected static function bootRecordsActivity()
    {
        if(auth()->guest()) return ;

        foreach (static::getActivitiesToRecord() as $event){
            static::$event(function ($model) use ($event){
               $model->recordActivity($event);
            });
        }

        static::deleting(function ($model){
           $model->activity()->delete();
        });
    }
    .
    .

我们在Trait中进行监听对应模型的deleting事件,所以当thread被删除时我们会将相关的动作流也进行删除。我们再次测试:
file
我们的 Bug 修复了吗?没有完全修复。因为当thread被删除时,与该thread相关的回复也会被删除,但是该回复的动作流却不会被删除。我们进一步进行修复:
forum\tests\Feature\CreateThreadsTest.php

.
.
/** @test */
public function authorized_users_can_delete_threads()
{
    $this->signIn();

    $thread = create('App\Thread',['user_id' => auth()->id()]);
    $reply = create('App\Reply',['thread_id' => $thread->id]);

    $response =  $this->json('DELETE',$thread->path());

    $response->assertStatus(204);

    $this->assertDatabaseMissing('threads',['id' => $thread->id]);
    $this->assertDatabaseMissing('replies',['id' => $reply->id]);

    $this->assertDatabaseMissing('activities',[
        'subject_id' => $thread->id,
        'subject_type' => get_class($thread)
    ]);

    $this->assertDatabaseMissing('activities',[
            'subject_id' => $reply->id,
            'subject_type' => get_class($reply)
        ]);
}
.
.

forum\app\Thread.php

.
.
protected static function boot()
{
    parent::boot();

    static::addGlobalScope('replyCount',function ($builder){
       $builder->withCount('replies');
    });

    static::deleting(function ($thread) {
        $thread->replies->each->delete();
    });
}
.
.

我们把批量删除与话题关联的回复改为逐条删除,使得Reply模型的deleting事件被监听到,从而删除与该回复相关的动作流。我们再次运行测试:
file
我们还能让测试更简洁一些:
forum\tests\Feature\CreateThreadsTest.php

.
.
/** @test */
public function authorized_users_can_delete_threads()
{
    $this->signIn();

    $thread = create('App\Thread',['user_id' => auth()->id()]);
    $reply = create('App\Reply',['thread_id' => $thread->id]);

    $response =  $this->json('DELETE',$thread->path());

    $response->assertStatus(204);

    $this->assertDatabaseMissing('threads',['id' => $thread->id]);
    $this->assertDatabaseMissing('replies',['id' => $reply->id]);

    $this->assertEquals(0,Activity::count());
}
.
.

运行全部测试:
file
现在 Bug 已经修复,你可以再次创建一个话题,并进行回复,然后删除该话题,查看个人页面进行确认。

注:在测试之前要先把最开始测试时生成的那条动作流从activities表中删除

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

上一篇 下一篇
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。