Menu

76.生成话题的 Slug(二)

本节说明

  • 对应视频教程第 76 小节:A Thread Should Have a Unique Slug: Part 2

本节内容

本节我们完成上一节未完成的功能:生成唯一的 Slug。我们选择的方式是给相同话题的 Slug 加上递增的后缀,如:title,title-2,title-3等。首先我们来新增一个测试:
forum\tests\Feature\CreateThreadsTest.php

    .
    .
    /** @test */
    public function a_thread_requires_a_valid_channel()
    {
        factory('App\Channel',2)->create(); // 新建两个 Channel,id 分别为 1 跟 2

        $this->publishThread(['channel_id' => null])
            ->assertSessionHasErrors('channel_id');

        $this->publishThread(['channel_id' => 999])  // channle_id 为 999,是一个不存在的 Channel
            ->assertSessionHasErrors('channel_id');
    }

    /** @test */
    public function a_thread_requires_a_unique_slug()
    {
        $this->signIn();

        $thread = create('App\Thread',['title' => 'Foo Title','slug' => 'foo-title']);

        $this->assertEquals($thread->fresh()->slug,'foo-title');

        $this->post(route('threads'),$thread->toArray());

        // 相同话题的 Slug 后缀会加 1,即 foo-title-2
        $this->assertTrue(Thread::whereSlug('foo-title-2')->exists());

        $this->post(route('threads'),$thread->toArray());

        // 相同话题的 Slug 后缀会加 1,即 foo-title-3
        $this->assertTrue(Thread::whereSlug('foo-title-3')->exists());
    }
    .
    .

然后我们选择用修改器的方式对 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' => request('title')
        ]);

        return redirect($thread->path())
            ->with('flash','Your thread has been published!');
    }
    .
    .

接着我们增加修改器:
forum\app\Thread.php

    .
    .
    public function setSlugAttribute($value)
    {
        if(static::whereSlug($slug = str_slug($value))->exists()) {
            $slug = $this->incrementSlug($slug);
        }

        $this->attributes['slug'] = $slug;
    }

    public function incrementSlug($slug)
    {
        // 取出最大 id 话题的 Slug 值
        $max = static::whereTitle($this->title)->latest('id')->value('slug');

        // 如果最后一个字符为数字
        if(is_numeric($max[-1])) {
            // 正则匹配出末尾的数字,然后自增 1 
            return preg_replace_callback('/(\d+)$/',function ($matches) {
                return $matches[1]+1;
            },$max);
        }

        // 否则后缀数字为 2
        return "{$slug}-2";
    }
}

运行测试:
file
运行全部测试:
file

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


zh117
关于 76 节的遗漏?
0 个点赞 | 0 个回复 | 问答