# PHPのフレームワークLaravelでAlgoliaを使うための環境構築 その3

👇の Live Coding Session - Advanced Search with Laravel and Algolia by Nuno Maduro を自分でも試しているのですが、

前回はPestでテストを走らせて、データベースがありませんがなエラーが出るところまでいきました。

ということで、 Pest.php を👇のようにしてRefreshDatabaseを呼ぶようにしてみました。

<?php

use Illuminate\Foundation\Testing\RefreshDatabase;

uses(Tests\TestCase::class, RefreshDatabase::class)->in('Feature');

すると👇のようにSQLiteのファイルがそれっぽくなっています。

sqlite

で、テスト流すと、20個プロダクトあるはずが0件ですよ、と。イイ感じになってきました。

$ ./vendor/bin/pest

   PASS  Tests\Unit\ExampleTest
  ✓ basic test

   FAIL  Tests\Feature\ExampleTest
  ⨯ has products

  ---

  • Tests\Feature\ExampleTest > has products
  Failed asserting that 0 matches expected 20.

# テストデータの準備

database -> migrationsの中でテストデータを準備するところの中に20個のProductを作るようにってことで👇のupメソッドの中で。

    public function up()
    {
        Schema::create('products', function (Blueprint $table) {
            $table->id();
            $table->timestamps();
        });

        factory(\App\Product::class, 20)->create();
    }

するとテストが通るようになりました!

$ ./vendor/bin/pest

   PASS  Tests\Unit\ExampleTest
  ✓ basic test

   PASS  Tests\Feature\ExampleTest
  ✓ has products

  Tests:  2 passed
  Time:   0.25s

# プロダクトの属性

Productがtitle, description, priceという属性を持っているかというテストを追加。

test('has a title, description, and a price', function() {
    $product  = Product::first();
    assertNotEmpty($product->title);
    assertNotEmpty($product->description);
    assertNotEmpty($product->price);
});

そして、CreateProductsTableクラスのupメソッドの中で👇のようにString型のTitleと、Text型のDescriptionとInteger型のPriceを追加。

        Schema::create('products', function (Blueprint $table) {
            $table->id();
            $table->string('title');
            $table->text('description');
            $table->integer('price');
            $table->timestamps();
        });

そしてテストを流すと、、👇何やらエラーが。

$ ./vendor/bin/pest

   PASS  Tests\Unit\ExampleTest
  ✓ basic test

   FAIL  Tests\Feature\ExampleTest
  ⨯ has products
  ⨯ has a title, description, and a price

  ---

  • Tests\Feature\ExampleTest > has products
   Illuminate\Database\QueryException 

  SQLSTATE[23000]: Integrity constraint violation: 19 NOT NULL constraint failed: products.title (SQL: insert into "products" ("updated_at", "created_at") values (2020-07-20 09:24:20, 2020-07-20 09:24:20))

  at vendor/laravel/framework/src/Illuminate/Database/Connection.php:671

これにはFakerというテスト用のモジュールを使って、、という流れ。ProductFactoryクラスのコードは👇

<?php

/** @var \Illuminate\Database\Eloquent\Factory $factory */

use App\Product;
use Faker\Generator as Faker;

$factory->define(Product::class, function (Faker $faker) {
    return [
        'title' => $faker->title,
        'description' => $faker->text,
        'price' => $faker->randomNumber(2)
    ];
});

で、テストをすると👇のように通りました〜

$ ./vendor/bin/pest

   PASS  Tests\Unit\ExampleTest
  ✓ basic test

   PASS  Tests\Feature\ExampleTest
  ✓ has products
  ✓ has a title, description, and a price

  Tests:  3 passed
  Time:   0.21s

そして、ExampleTestってクラス名が微妙だよねってことで、ProductTestという名前に変更。

./vendor/bin/pest をしてテストが成功するのを確認したらいよいよ、、

# Algoliaにデータを送る

ここでLaravel Scoutを使う。通常は👇でインストールするけど、

composer require laravel/scout

👇のAlgolia拡張版の方を入れると、基本的にはLaravel Scoutと同じだけど、Algolia用の実装が追加されている、とのこと。

composer require algolia/scout-extended

実際に中身を見ていくと👇のようにlaravel/scoutやalgoliasearch-client-phpが入っています、と。

Package operations: 4 installs, 0 updates, 0 removals
  - Installing riimu/kit-phpencoder (v2.4.0): Downloading (100%)         
  - Installing laravel/scout (v8.1.0): Downloading (100%)         
  - Installing algolia/algoliasearch-client-php (2.7.0): Downloading (100%)         
  - Installing algolia/scout-extended (v1.9.0): Downloading (100%)     

# Productモデルを検索可能にする

Product.phpにて👇のようにSearchable。

<?php

namespace App;

use Laravel\Scout\Searchable;
use Illuminate\Database\Eloquent\Model;

class Product extends Model
{
    use Searchable;
}

テスト書くよ、と。👇のように検索した結果がローカルのデータベースと同じ件数であること。

test('has search', function() {
    $response = Product::search();
    assertEquals($response->count(), Product::count());
});

YouTube上ではテストが成功していますが、何もAlgoliaの設定を入れていないので👇のようにテストは失敗します。

a$ ./vendor/bin/pest

   PASS  Tests\Unit\ExampleTest
  ✓ basic test

   FAIL  Tests\Feature\ProductTest
  ⨯ has products
  ⨯ has a title, description, and a price
  ⨯ has search

  ---

  • Tests\Feature\ProductTest > has products
   Algolia\AlgoliaSearch\Exceptions\UnreachableException 

  Impossible to connect, please check your Algolia Application Id.

  at vendor/algolia/algoliasearch-client-php/src/RetryStrategy/ApiWrapper.php:187

そして、何のことやらよくわかってないですが(笑)、Laravel Scoutの設定ファイル(?)をpublishします。

$ php artisan vendor:publish

 Which provider or tag's files would you like to publish?:
  [0 ] Publish files from all providers and tags listed below
  [1 ] Provider: Facade\Ignition\IgnitionServiceProvider
  [2 ] Provider: Fideloper\Proxy\TrustedProxyServiceProvider
  [3 ] Provider: Fruitcake\Cors\CorsServiceProvider
  [4 ] Provider: Illuminate\Foundation\Providers\FoundationServiceProvider
  [5 ] Provider: Illuminate\Mail\MailServiceProvider
  [6 ] Provider: Illuminate\Notifications\NotificationServiceProvider
  [7 ] Provider: Illuminate\Pagination\PaginationServiceProvider
  [8 ] Provider: Laravel\Scout\ScoutServiceProvider
  [9 ] Provider: Laravel\Tinker\TinkerServiceProvider
  [10] Tag: cors
  [11] Tag: flare-config
  [12] Tag: ignition-config
  [13] Tag: laravel-errors
  [14] Tag: laravel-mail
  [15] Tag: laravel-notifications
  [16] Tag: laravel-pagination
 > 8

Copied File [/vendor/laravel/scout/config/scout.php] To [/config/scout.php]
Publishing complete.

そして、configディレクトリのscout.phpをみると👇のような設定箇所があります。

    'algolia' => [
        'id' => env('ALGOLIA_APP_ID', ''),
        'secret' => env('ALGOLIA_SECRET', ''),
    ],

ってことで、.envファイルにAlgoliaのクレデンシャルを追加していきます。

ALGOLIA_APP_ID=xxx
ALGOLIA_SECRET=xxx

で、テストすると、今度はAlgolia側にproductsっていうインデックスが無いよ、と。データベースはテーブル作るとこからやってくれるけど、Algoliaに関してはインデックスは自分で作っておきなさいって感じなのかな〜

$ ./vendor/bin/pest

   PASS  Tests\Unit\ExampleTest
  ✓ basic test

   FAIL  Tests\Feature\ProductTest
  ✓ has products
  ✓ has a title, description, and a price
  ⨯ has search

  ---

  • Tests\Feature\ProductTest > has search
   Algolia\AlgoliaSearch\Exceptions\NotFoundException 

  Index products does not exist

  at vendor/algolia/algoliasearch-client-php/src/RetryStrategy/ApiWrapper.php:208

って、Algoliaのダッシュボードみたらproductsインデックスは既にあって、データもそれっぽいのが20件入ってますよ、と。ってか、タイトルがDr.とかMr.とかなのがちょっとウケというか、なんというかソレじゃない感。笑

title

そして、もっかいテスト流したら通ったので、indexを作ってる間にテストが流れちゃってたとかそんな感じかな、と。

$ ./vendor/bin/pest

   PASS  Tests\Unit\ExampleTest
  ✓ basic test

   PASS  Tests\Feature\ProductTest
  ✓ has products
  ✓ has a title, description, and a price
  ✓ has search

  Tests:  4 passed
  Time:   0.74s

ということで、今日はAlgoliaとやりとりするところまで出来ました。

このエントリーをはてなブックマークに追加

Algolia検索からの流入のみConversionボタン表示