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 还要是唯一的,我们将在下一节完成。
          
TDD 构建 Laravel 论坛笔记
                    
                    
            
            
                关于 LearnKu
              
                    
                    
                    
 
推荐文章: