Menu

95.全文搜索(二)

本节说明

  • 对应视频教程第 95 小节:First Class Search: Implementation

本节内容

上一节我们初步了解了ScoutAlgolia ,这一节我们初步实现话题搜索功能。我们依然是从新建测试开始:
forum\tests\Feature\SearchTest.php

<?php

namespace Tests\Feature;

use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;

class SearchTest extends TestCase
{
    use RefreshDatabase;

    /** @test */
    public function a_user_can_search_threads()
    {
        $search = 'foobar';

        create('App\Thread',[],2);
        create('App\Thread',['body' => "A thread with {$search} term."],2);

        $results = $this->getJson("/threads/search?q={$search}")->json();

        $this->assertCount(2,$results['data']);
    }
}

添加路由:
forum\routes\web.php

.
Route::get('threads/create','ThreadsController@create');

Route::get('threads/search','SearchController@show');
.

新建控制器并添加show()方法:

$ php artisan make:controller SearchController

forum\app\Http\Controllers\SearchController.php

<?php

namespace App\Http\Controllers;

use App\Thread;

class SearchController extends Controller
{
    public function show()
    {
        $search = request('q');

        return Thread::search($search)->paginate(20);
    }
}

运行测试:
file
我们搜索出来的结果也会显示在页面上,所以我们来修改下代码:

<?php

namespace App\Http\Controllers;

use App\Thread;
use App\Trending;

class SearchController extends Controller
{
    public function show(Trending $trending)
    {
        $search = request('q');

        $threads = Thread::search($search)->paginate(20);

        if (request()->expectsJson()) {
            return $threads;
        }

        return view('threads.index',[
            'threads' => $threads,
            'trending' => $trending->get()
        ]);
    }
}

再次运行测试:
file
但是现在有一个问题需要我们解决。由于我们在forum\config\scout.php设置的驱动是algolia

.
'driver' => env('SCOUT_DRIVER', 'algolia'),
.

因此在我们每次新建话题时,话题都会被同步到 Algolia 上,比如刚刚测试的时候新建的话题:
file
我们并不需要每次都进行同步,所以我们进行下处理,只在刚刚的测试中应用algolia驱动进行同步,其他的测试则不应用algolia驱动:
forum\phpunit.xml

    .
    .
    <php>
        <env name="APP_ENV" value="testing"/>
        <env name="DB_CONNECTION" value="sqlite"/>
        <env name="DB_DATABASE" value=":memory:"/>
        <env name="CACHE_DRIVER" value="array"/>
        <env name="SESSION_DRIVER" value="array"/>
        <env name="QUEUE_DRIVER" value="sync"/>
        <env name="SCOUT_DRIVER" value="null"/>
    </php>
</phpunit>

并且,在刚才的测试中,我们应用algolia驱动,还要在测试之后删除我们的测试数据:
forum\tests\Feature\SearchTest.php

<?php

namespace Tests\Feature;

use App\Thread;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;

class SearchTest extends TestCase
{
    use RefreshDatabase;

    /** @test */
    public function a_user_can_search_threads()
    {
        // 启用驱动
        config(['scout.driver' => 'algolia']);

        $search = 'foobar';

        create('App\Thread',[],2);
        create('App\Thread',['body' => "A thread with {$search} term."],2);

        // 由于网络等因素,所以我们进行以下处理
        do {
            sleep(.25);

            $results = $this->getJson("/threads/search?q={$search}")->json();
        } while (empty($results));

        $this->assertCount(2,$results['data']);

        // 删除测试数据
        Thread::latest()->take(4)->unsearchable();
    }
}

运行全部测试:
file
现在我们在话题列表页面加上搜索功能:
forum\resources\views\threads\index.blade.php

@extends('layouts.app')

@section('content')
    <div class="container">
        <div class="row">
            <div class="col-md-8">
                @include ('threads._list')

                {{ $threads->render() }}
            </div>

            <div class="col-md-4">
                <div class="panel panel-default">
                    <div class="panel-heading">
                        Search
                    </div>

                    <div class="panel-body">
                        <form method="GET" action="/threads/search">
                            <div class="form-group">
                                <input type="text" name="q" placeholder="Search for something..." class="form-control">
                            </div>

                            <div class="form-group">
                                <button class="btn btn-default" type="submit">Search</button>
                            </div>
                        </form>
                    </div>
                </div>

                @if(count($trending))
                .
                .

进行搜索:
file

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


暂无话题~