【Laravel】Factoryで独自に商品のテストデータを用意する

さてさて、これはLaravelに限らずですがウェブサイトを構築するに当たって多くの場合であると便利だな、というものがあります。

それが、「テストデータ」です。

例えば、テストユーザーを何人か登録しておいてログイン機能をテストしたり、取り扱っている商品のテストデータを作って検索がうまくいくかチェックしてみたりと、テストデータを用意することで開発を効率的にすることができます。

そして、Laravelではこのテストデータの作成にはfzaninotto/Fakerという有名パッケージを使っていて、特別何もインストールしなくてもそのまま使えます。

ただし、Fakerは名前や住所などよく使うデータには対応しているものの(しかも日本語OKのものもあります)、やはり独自で作らないといけないものもあります。

そこで!

今回は、Fakerを拡張してテストデータを作成する方法を紹介します。

ぜひ皆さんのお役に立てると嬉しいです😊✨

 

開発環境: Laravel 6.0

やりたいこと

今回は、Fakerを使って「DIYや工具」の商品データを作成します。

※データ取得はYahoo ショッピングの商品検索APIを使うので、カテゴリIDを変更すればお好きな商品に変更することができます。

前提として

上の項目でも書きましたが、今回のコードではYahooショッピングAPIのデータを使って実装します。そのため、バーコード・スキャナーでIBSNを読み取って本の入荷処理をする「準備する」を参考にしてClient IDを取得しておいてください。

そして、取得したClient IDは以下のように.envに追加しておいてください。

YAHOO_APPID=(あなたのClient ID)

では実際にコードを書いていきましょう!

商品データのテーブル、モデルを用意する

まずは、テストデータを登録するためのDBテーブルと、その管理をするモデルを作成します。

以下のコマンドを実行してください。

php artisan make:model Product -m

これで、モデルProductproductsテーブルのマイグレーションが作成されました。

では、作成されたdatabase/migrations/****_**_**_******_create_products_table.phpを開いてup()を次のように変更しましょう。

public function up()
{
    Schema::create('products', function (Blueprint $table) {
        $table->bigIncrements('id');
        $table->string('name')->comment('商品名');
        $table->string('code')->comment('商品コード');
        $table->integer('price')->comment('価格');
        $table->timestamps();
    });
}

変更が終わったら、マイグレーションを実行してください。

php artisan migrate

実行するとテーブルこのようになります。

Fakerの独自プロバイダーを作成する

専用のServiceProviderをつくる

php artisan make:provider FakerServiceProvider

すると、app/Providers/FakerServiceProvider.phpが作成されるので中身を以下のように変更してください。

<?php

namespace App\Providers;

use App\Faker\Product;
use Faker\Factory as FakerFactory;
use Faker\Generator as FakerGenerator;
use Illuminate\Support\ServiceProvider;

class FakerServiceProvider extends ServiceProvider
{
    /**
     * Register services.
     *
     * @return void
     */
    public function register()
    {
        $this->app->singleton(FakerGenerator::class, function ($app) {

            $faker = FakerFactory::create($app['config']->get('app.faker_locale', 'en_US'));
            $faker->addProvider(new Product($faker));
            return $faker;

        });
    }

    /**
     * Bootstrap services.
     *
     * @return void
     */
    public function boot()
    {
        //
    }
}

変更したら、このServiceProviderLaravelへ登録します。

'providers' => [

    // 省略

    App\Providers\FakerServiceProvider::class

],

Faker用の独自クラスをつくる

FakerServiceProviderではApp\Faker\Productというクラスを利用していますが、まだ存在していないので作成していきましょう。

まず、app/Faker/Product.phpというファイルを作成してください。(Fakerフォルダも無いので作成してください)

そして、中身は以下のようにします。

<?php

namespace App\Faker;

use Illuminate\Support\Arr;

class Product extends \Faker\Provider\Base
{
    private $_products = [];

    public function product($parameters) {

        if(empty($this->_products)) {

            $this->_products = $this->getProducts($parameters);

        }

        return Arr::random($this->_products);

    }

    private function getProducts($parameters) {

        $parameters['appid'] = env('YAHOO_APPID');
        $url = 'https://shopping.yahooapis.jp/ShoppingWebService/V1/json/itemSearch?'. http_build_query($parameters);
        $json = file_get_contents($url);
        $data = json_decode($json, true);

        $products = [];
        $total = intval($data['ResultSet']['totalResultsReturned']);

        for($i = 0 ; $i < $total ; $i++) {

            $product = $data['ResultSet'][0]['Result'][$i];

            $products[] = [
                'name' => $product['Name'],
                'code' => $product['Code'],
                'price' => $product['Price']['_value'],
            ];

        }

        return $products;

    }
}

やっていることはシンプルで、getProducts()の中でYahoo APIにアクセスして必要な情報を取得、そして、Arr::random()でその中からランダムに商品データを返すようにしているだけです。

テストデータを追加してみる

では、ここまででつくったFakerの独自プロバイダーが使えるかどうかをLaravelのテストデータ機能FactorySeederを使って試してみましょう。

Factoryをつくる

まず、Factoryをつくりましょう。
Factoryはテストデータを作成するパッケージFakerをより使いやすくするためのもので、例えば以下のようにするだけで毎回違うテストデータを用意することが出来るようになります。

factory(App\User::class)->create();

では、以下のコマンドを実行してください。

php artisan make:factory ProductFactory

そして、作成されたdatabase/factories/ProductFactory.phpを開いて$factory->define()を以下のように変更します。

$factory->define(Product::class, function (Faker $faker) {

    $parameters = [
        'category_id' => 2503,  // DIY、工具,
        'hits' => 50            // 50件取得
    ];
    return $faker->product($parameters);

});

Seederをつくる

続いてはSeederです。
以下のコマンドでファイルを作成しましょう。

php artisan make:seed ProductsTableSeeder

すると、database/seeds/ProductsTableSeeder.phpが作成されるのでrun()を以下のように変更します。

public function run()
{
    for($i = 0 ; $i < 25 ; $i++) {

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

    }
}

変更が完了したら、ProductsTableSeederLaravelに登録しておきます。database/seeds/DatabaseSeeder.phpを開いて以下のように追加しておいてください。

<?php

use Illuminate\Database\Seeder;

class DatabaseSeeder extends Seeder
{
    /**
     * Seed the application's database.
     *
     * @return void
     */
    public function run()
    {
         //$this->call(UsersTableSeeder::class);
         $this->call(ProductsTableSeeder::class);
    }
}

これで作業は完了です!

実際にテストしてみる

では、ここまでで作成したFactorySeederを実行してみましょう。

php artisan migrate:fresh --seed

実行結果はこうなりました。

完成です!😊✨

ちなみに

ちなみに、今回紹介したYahoo ショッピングAPIは2020年6月30日で終了し、新しいAPIが2019年12月に登場するそうですので、ゆくゆくはコードを変更する必要がでてくると思います。

おわりに

ということで、今回はFakerを拡張して独自プロバイダーをつくり、テストの商品データが使えるようにしてみました。

実は当初は他のダミーデータ作成サイトからスクレイピングすることも考えましたが、いつまで提供を続けるかが未知数なので今回はYahoo APIを使うことにしました。(といってもそのAPIも・・・「ちなみに」をご覧ください😅)

ただ、今回のテクニックを使えば独自に好きなバンド名やタレント名、漫画などの登場人物などをテストデータとして使えるようになりますので、開発のモチベーションを少しだけアップさせられるかもしれません。

ぜひ皆さんも活用してみてくださいね。

ではでは〜!

この記事が役立ちましたらシェアお願いします😊✨