Menu

49.垃圾内容检测机制(一)

本节说明

  • 对应视频教程第 49 小节:Spam Detection

本节内容

在开始本节内容之前,我们先来完成应该在上一节完成的工作:运行全部测试。
file
测试报错,因为我们需要进行以下修改:
forum\resources\views\threads\index.blade.php

    .
    .
    <h4 class="flex">
        <a href="{{ $thread->path() }}">
            @if(auth()->check() && $thread->hasUpdatesFor(auth()->user()))
                <strong>
                    {{ $thread->title }}
                </strong>
            @else
                {{ $thread->title }}
            @endif
        </a>
    </h4>
    .
    .

在上一节中,我们使用了$thread->hasUpdatesFor(auth()->user())。但是我们忘记考虑未登录用户的情形,所以产生了报错。修复后再次运行全部测试:
file
现在正式开始本节内容。本节我们将开始构建一系列垃圾探测器,用来过滤垃圾回复、话题等内容。对于一个论坛而言,这些几乎是不可避免的问题,我们将从关键字检测开始。首先我们新建一个测试:
forum\tests\Feature\ParticipateInForumTest.php

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

        $thread = create('App\Thread');
        $reply = make('App\Reply',[
           'body' => 'something forbidden'
        ]);

        $this->expectException(\Exception::class);

        $this->post($thread->path() . '/replies',$reply->toArray());
    }
}

为了让测试通过,我们 Hard Codeing 一下:
forum\app\Http\Controllers\RepliesController.php

    .
    .
    public function store($channelId,Thread $thread)
    {
        $this->validate(request(),['body' => 'required']);

        if(stripos(request('body'),'something forbidden') !== false){
            throw new \Exception('Your reply contains spam.');
        }

        $reply = $thread->addReply([
            'body' => request('body'),
            'user_id' => auth()->id(),
        ]);

        if(request()->expectsJson()){
            return $reply->load('owner');
        }

        return back()->with('flash','Your reply has been left.');
    }
    .
    .

运行测试:
file
虽然测试通过了,但是我们都知道以上的代码只是权宜之计,因为我们的关键词检测必然要求是可扩展的。接下来我们来新建一个测试文件:
forum\tests\Unit\SpamTest.php

<?php

namespace Tests\Unit;

use Tests\TestCase;
use App\Spam;

class SpamTest extends TestCase
{
    /** @test */
    public function it_validates_spam()
    {
        $spam = new Spam();

        $this->assertFalse($spam->detect('Innocent reply here.'));
    }
}

我们建立的第一个测试十分简单,它仅仅测试是否会进行关键词检测。为了通过测试,我们还需要Spam类文件以及detect方法:
forum\app\Spam.php

<?php

namespace App;

class Spam
{
    public function detect($body)
    {
        $this->detectInvalidKeywords($body);

        return false;
    }

    public function detectInvalidKeywords($body)
    {
        $invalidKeywords = [
            'something forbidden'
        ];

        foreach ($invalidKeywords as $invalidKeyword){
            if(stripos($body,$invalidKeyword) !== false){
                throw new \Exception('Your reply contains spam.');
            }
        }

    }
}

detect中,我们调用detectInvalidKeywords()方法检测关键词:如果有配置好的关键词,则抛出异常;否则,返回false。我们来测试一下:
file
现在我们可以修改检测关键词的代码:
forum\app\Http\Controllers\RepliesController.php

    .
    .
    public function store($channelId,Thread $thread,Spam $spam)
    {
        $this->validate(request(),['body' => 'required']);

        $spam->detect(request('body'));

        $reply = $thread->addReply([
            'body' => request('body'),
            'user_id' => auth()->id(),
        ]);

        if(request()->expectsJson()){
            return $reply->load('owner');
        }

        return back()->with('flash','Your reply has been left.');
    }
    .
    .

注:别忘了顶部Spam的引用。

再次运行一下我们上一个测试:
file
测试通过。我们将在下一节进行一些更深入地探讨。

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


暂无话题~
刻意练习,每日精进。
1
点赞
58
浏览
0
讨论

维护者