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 网站上。

上一篇 下一篇
《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。