40.话题订阅(一)
- 本系列文章为
laracasts.com
的系列视频教程——Let's Build A Forum with Laravel and TDD 的学习笔记。若喜欢该系列视频,可去该网站订阅后下载该系列视频, 支持正版 ;- 视频源码地址:github.com/laracasts/Lets-Build-a-...;
- 本项目为一个 forum(论坛)项目,与本站的第二本实战教程 《Laravel 教程 - Web 开发实战进阶》 类似,可互相参照。
本节说明
- 对应视频教程第 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
现在我们来运行测试:
测试通过,但是我们的测试逻辑并不严谨,我们需要完善它:
.
.
/** @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()
);
}
}
运行测试:
测试未通过,因为我们还没有定义subscribe()
方法:
forum\app\Thread.php
.
.
public function subscribe($userId = null)
{
$this->subscriptions()->create([
'user_id' => $userId ?: auth()->id()
]);
return $this;
}
.
.
运行测试:
批量赋值错误,我们需要为ThreadSubscription
模型设置可更新属性:
forum\app\ThreadSubscription.php
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class ThreadSubscription extends Model
{
protected $guarded =[];
}
再次运行测试:
我们可以传参给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()
);
}
}
再次运行测试,仍然通过:
现在我们可以继续前进了。既然已经有了订阅的测试,理所应当也要有取消订阅的测试。我们来建立该测试:
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();
}
.
.
运行测试:
最后,我们来运行一下全部测试: