75.生成话题的 Slug(一)
- 本系列文章为
laracasts.com
的系列视频教程——Let's Build A Forum with Laravel and TDD 的学习笔记。若喜欢该系列视频,可去该网站订阅后下载该系列视频, 支持正版 ;- 视频源码地址:github.com/laracasts/Lets-Build-a-...;
- 本项目为一个 forum(论坛)项目,与本站的第二本实战教程 《Laravel 教程 - Web 开发实战进阶》 类似,可互相参照。
本节说明
- 对应视频教程第 75 小节:A Thread Should Have a Unique Slug: Part 1
本节内容
本节我们开始开发话题的 Slug。我们想让话题被创建的时候生成 Slug,并且是唯一的。我们首先来修改a_thread_can_make_a_string_path
测试:
forum\tests\Unit\ThreadTest.php
.
.
/** @test */
public function thread_has_a_path() // 修改测试命名,更具可读性
{
$thread = create('App\Thread');
$this->assertEquals("/threads/{$thread->channel->slug}/{$thread->slug}",$thread->path());
}
.
.
我们在测试中认为$thread->path()
与话题的slug
字段有关,但是现在我们的相关逻辑还没有建立,我们依次建立。首先我们修改迁移文件:
forum\database\migrations{timestamp}_create_threads_table.php
.
.
public function up()
{
Schema::create('threads', function (Blueprint $table) {
$table->increments('id');
$table->string('slug')->unique();
$table->unsignedInteger('user_id');
$table->unsignedInteger('channel_id');
$table->unsignedInteger('replies_count')->default(0);
$table->unsignedInteger('visits')->default(0);
$table->string('title');
$table->text('body');
$table->timestamps();
});
}
.
.
为了测试方便,我们修改模型工厂文件:
forum\database\factories\ModelFactory.php
.
.
$factory->define(App\Thread::class,function ($faker){
$title = $faker->sentence;
return [
'user_id' => function () {
return factory('App\User')->create()->id;
},
'channel_id' => function () {
return factory('App\Channel')->create()->id;
},
'title' => $title,
'body' => $faker->paragraph,
'visits' => 0,
'slug' => str_slug($title)
];
});
.
.
然后我们来修改path()
方法:
forum\app\Thread.php
.
.
public function path()
{
return "/threads/{$this->channel->slug}/{$this->slug}";
}
.
.
现在我们来运行测试:
测试通过,但是我们还没有在新建话题的时候为话题生成 Slug。我们来生成 Slug:
forum\app\Http\Controllers\ThreadsController.php
.
.
public function store(Request $request)
{
$this->validate($request,[
'title' => 'required|spamfree',
'body' => 'required|spamfree',
'channel_id' => 'required|exists:channels,id'
]);
$thread = Thread::create([
'user_id' => auth()->id(),
'channel_id' => request('channel_id'),
'title' => request('title'),
'body' => request('body'),
'slug' => str_slug(request('title'))
]);
return redirect($thread->path())
->with('flash','Your thread has been published!');
}
.
.
我们运行新建话题的测试:
我们新建话题,然后跳转到话题的详情页面。但是请记住,在目前我们传入路由的是话题实例,然后路由会默认传入的路由参数为话题的 ID:
Route::get('threads/{channel}/{thread}','ThreadsController@show');
所以我们修改匹配的路由参数为话题的 Slug 即可:
forum\app\Thread.php
.
.
public function getRouteKeyName()
{
return 'slug';
}
}
现在我们运行全部测试:
运行迁移:
$ php artisan migrate:refresh
进入Tinker:
$ php artisan tinker
填充数据:
>>> factory('App\Thread',30)->create();
现在我们访问话题详情页:
目前我们完成了生成 Slug 的逻辑,但是我们期望的是 Slug 还要是唯一的,我们将在下一节完成。