40.话题订阅(一)

未匹配的标注

本节说明

  • 对应视频教程第 40 小节:Thread Subscriptions(Part 1)

本节内容

在接下里的几个章节中,我们来完成话题订阅的功能:当你订阅了的话题有新回复时,你将会收到提醒。首先我们来建立测试逻辑:
forum\tests\Unit\ThreadTest.php

    .
    .
    /** @test */
    public function a_thread_can_be_subscribed_to()
    {
        // Given we have a thread
        // And an authenticated user
        // When the user subscribes to the thread
        // Then we should be able to fetch all threads that the user has subscribed to.
    }
}

根据测试逻辑填充代码:

    .
    .
    /** @test */
    public function a_thread_can_be_subscribed_to()
    {
        // Given we have a thread
        $thread = create('App\Thread');

        // And an authenticated user
        $this->signIn();

        // When the user subscribes to the thread
        $thread->subscribe();

        // Then we should be able to fetch all threads that the user has subscribed to.
        $thread->subscriptions()->where('user_id',auth()->id())->get();
    }
}

现在我们的测试是不通过的,因为我们需要定义subscribe()subscriptions()
forum\app\Thread.php

    .
    .
    public function subscribe()
    {

    }

    public function subscriptions()
    {
        return $this->hasMany(ThreadSubscription::class);
    }
}

建立ThreadSubscription模型:

$ php artisan make:model ThreadSubscription -m

修改迁移文件,建立表结构:
forum\database\migrations{timestamp}_create_thread_subscriptions_table.php

<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateThreadSubscriptionsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('thread_subscriptions', function (Blueprint $table) {
            $table->increments('id');
            $table->unsignedInteger('user_id');
            $table->unsignedInteger('thread_id');
            $table->timestamps();

            $table->foreign('thread_id')
                ->references('id')
                ->on('threads')
                ->onDelete('cascade');
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('thread_subscriptions');
    }
}

注意,我们在此处启用了外键约束。

运行数据库迁移:

$ php artisan migrate

现在我们来运行测试:
file
测试通过,但是我们的测试逻辑并不严谨,我们需要完善它:

    .
    .
    /** @test */
    public function a_thread_can_be_subscribed_to()
    {
        // Given we have a thread
        $thread = create('App\Thread');

        // And an authenticated user
        $this->signIn();

        // When the user subscribes to the thread
        $thread->subscribe();

        // Then we should be able to fetch all threads that the user has subscribed to.
        $this->assertEquals(
            1,
            $thread->subscriptions()->where('user_id',auth()->id())->count()
        );
    }
}

运行测试:
file
测试未通过,因为我们还没有定义subscribe()方法:
forum\app\Thread.php

    .
    .
    public function subscribe($userId = null)
    {
        $this->subscriptions()->create([
           'user_id' => $userId ?: auth()->id()
        ]);

        return $this;
    }
    .
    .

运行测试:
file
批量赋值错误,我们需要为ThreadSubscription模型设置可更新属性:
forum\app\ThreadSubscription.php

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class ThreadSubscription extends Model
{
    protected $guarded =[];
}

再次运行测试:
file
我们可以传参给subscribe()方法,所以我们的测试可以稍微进行下修改:

    .
    .
    /** @test */
    public function a_thread_can_be_subscribed_to()
    {
        // Given we have a thread
        $thread = create('App\Thread');

        // When the user subscribes to the thread
        $thread->subscribe($userId = 1);

        // Then we should be able to fetch all threads that the user has subscribed to.
        $this->assertEquals(
            1,
            $thread->subscriptions()->where('user_id',$userId)->count()
        );
    }
}

再次运行测试,仍然通过:
file
现在我们可以继续前进了。既然已经有了订阅的测试,理所应当也要有取消订阅的测试。我们来建立该测试:
forum\tests\Unit\ThreadTest.php

    .
    .
    /** @test */
    public function a_thread_can_be_unsubscribed_from()
    {
        // Given we have a thread
        $thread = create('App\Thread');

        // And a user who is subscribed to the thread
        $thread->subscribe($userId = 1);

        $thread->unsubscribe($userId);

        $this->assertCount(0,$thread->subscriptions);
    }
}

接下来新建unsubscribe()方法:
forum\app\Thread.php

    .
    .
    public function subscribe($userId = null)
    {
        $this->subscriptions()->create([
           'user_id' => $userId ?: auth()->id()
        ]);

        return $this;
    }

    public function unsubscribe($userId = null)
    {
        $this->subscriptions()
            ->where('user_id',$userId ?: auth()->id())
            ->delete();
    }
    .
    .

运行测试:
file
最后,我们来运行一下全部测试:
file

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

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


暂无话题~