Menu

75.生成话题的 Slug(一)

本节说明

  • 对应视频教程第 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}";
    }
    .
    .

现在我们来运行测试:
file
测试通过,但是我们还没有在新建话题的时候为话题生成 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!');
    }
    .
    .

我们运行新建话题的测试:
file
我们新建话题,然后跳转到话题的详情页面。但是请记住,在目前我们传入路由的是话题实例,然后路由会默认传入的路由参数为话题的 ID:

Route::get('threads/{channel}/{thread}','ThreadsController@show');

所以我们修改匹配的路由参数为话题的 Slug 即可:
forum\app\Thread.php

    .
    .
    public function getRouteKeyName()
    {
        return 'slug';
    }
}

现在我们运行全部测试:
file
运行迁移:

$ php artisan migrate:refresh

进入Tinker:

$ php artisan tinker

填充数据:

>>> factory('App\Thread',30)->create();

现在我们访问话题详情页:
file
目前我们完成了生成 Slug 的逻辑,但是我们期望的是 Slug 还要是唯一的,我们将在下一节完成。

本文章首发在 Laravel China 社区
上一篇 下一篇
讨论数量: 0
发起讨论


暂无话题~