top of page
執筆者の写真英伸 後

Laravel演習 07 SEEDER と FACTORY


 

テストデータ作成


Laravelを使ったWEBアプリとデータベース連携の実演を行う前にXamppで作成したデータベースに実演用のテストデータを作りたいと思います。

最初の設定時にデータベース名「dmena」に「corporations」というテーブルを作成しました。

現時点では入れ物を作っただけで、データの主体となるレコードが一件も登録されていません。


テストデータを手入力で作っても構わないのですが、LaravelにはSEEDERとFACTORYというクラスが用意されていて、このテストデータを任意の数だけ自動的に生成する仕組みがあります。


Seederについて

  • 最初から用意しておくデータのことをシードといいます。

  • このシードを作成することをシーディングといいます。

  • Laravelにはこのシーディング機能があり、その機能を提供するクラスをシーダーといいます。

  • このSEEDERクラスはプロジェクトの中 \DMENA\vendor\laravel\framework\src\Illuminate\Database\Seeder.php に収納されています。

  • SEEDERは一発で任意のフィールド、任意の数のダミーデータをDB上に登録する機能をもっていますが、SEEDER単体では登録するデータをSEEDERの中に開発者が手で書きこんでいく必要があります。

  • データの作成をランダムに自動的に行う機能がFACTORYで、SEEDERとこのFACTORYとが連携することでダミーデータの生成を格段に行うことができます。


Seederの使い方


artisan コマンドで 


① php artisan make:seeder ファイル名


を叩きます。

database\seeders 配下に所定の名称のSeederファイルが作成されます。

ファイルを作成したら


② Seederファイルの中を編集します。


run()メソッドが用意されていますので、その中を書いてゆきます。


③ Seederファイルの編集が完了したら DatabaseSeeder.php にこのSeederファイルを登録します。


④ php artisan db:seed を叩きます


DatabaseSeeder.php に登録された各Seederが呼び出されてDB操作を行います。


Factoryについて

  • Eloquentモデルを使ってテストデータを自動的に生成するツールです。

  • 例えば、Userモデルというのを作っている場合、そこに定義した各フィールド、例えばユーザー名やメールアドレスと項目に収容するデータをランダムに作ってくれます。

  • Factoryで作ったランダムデータをSeederでDBに登録する。こうしてテストデータが作成できるわけです。

  • 各フィールドに定義づけを行えば(例えば人名にはname() を適用する)一定のルールに従ったランダムデータがいくつでも生成できます。

Factoryの使い方


artisan コマンドで


php artisan make:factory ファイル名


を叩きます。


②database\factories 配下に所定のFactoryファイルが作成されます。


ファイルを作成したら


③ Factoryファイルの中身を編集します。


FakerクラスからFaker PHPライブラリというのを引用してランダム文字列のパターンを定義してゆきます。


<実演>


 

Configの設定変更


Factoryを利用してランダム文字列を生成する際に日本語が扱えるようにConfigの設定変更をします。

config > app.php の109行目 'faker_locale' => 'en_US' を

'faker_locale' => 'ja_JP' に変更します。


Seedファイルの生成


Seederとして 「CorporationTableSeeder.php」 を生成します。

artisan コマンドを叩きます。


php artisan make:seeder CorporationTableSeeder



Seeder created successfully. とコメントが表示されます。


ディレクトリ database > seeders 配下に「CorporationTableSeeder.php」が生成されていることが確認できます。

真下にある 「DatadbaseSeeder.php」 はSeederファイルを束ねる役割を持っています。


Factoryファイルの作成


同じようにFactoryファイルとして 「CorporationFactory.php」 を生成します。

artisanコマンドを叩きます。


php artisan make:factory CorporationFactory


Factory created successfully. とコメントが表示されます。


ディレクトリ database > seeders 配下に「CorporationFactory.php」が生成されていることが確認できます。


Seederファイルの編集準備


生成されたSeederファイルを見てみます。


①namespace として Database\Seeders に配置されていることが記載されています。

次に


②use Illminate\Database\Seeder


Seederクラスを引用しています。


③class CorporationTableSeeder extends Seeder


そして、このクラス CorporationTableSeeder はSeederクラスを継承しています。


④CorporationTableSeeder クラスにはただひとつ run() メソッドが実装されています。

このrun()メソッドの中にデータ生成処理を書いていきます。


今回はModelを利用してここを記述してゆきます。

Modelは app\Models\Corporation.php です。

このModelを使うわけですからSeederファイルに


use App\Models\Corporation

と記述します(\はバックスラッシュ、拡張子の.php は不要)


そしてrun() の中にfactory でデータを入れていくわけです。

Seederファイルの編集はいったんここで保留しておきます。


Factoryファイルの編集


生成された 「CorporationFactory.php」を見てみます。


①namespace として Database\Factories に配置されていることが確認できます。


次の


②use App\Models\Corporation;

③use Illuminate\Database\Eloquent\Factories\Factory;


でModelとして設営したCorporationクラスとFactoryクラスを引用します。


④class CorporationFactory extends Factory


CorporationFactoryクラスはこのFactoryクラスを継承しています。

このクラスの中


⑤protected $model = Corporation::class;


は外部クラスであるCorporationモデルのclassプロパティを呼び出して$model に収納している。

何に使うのかは現時点では不明。


⑥difinition() メソッド、returnの中にダミーデータ生成のためのコードを書いてゆきます。


この「CorporationFactory.php」はモデル Corporationクラスを継承しています。

ですので、Corporationクラスで定義されたカラムを特段の準備なしに引用することができます。


return の中でダミーデータを生成させるためにはFakerというものを使います。

FakerはFaker PHP ライブラリというものにアクセスして、会社名や生年月日などに対してランダムなのだけれどそれらしい文字列を自動的に生成します。

例えば、Fakerのプロパティであるcompany()メソッドを実行するとFaker PHP ライブラリに定義されている文字列生成ルールに基づいて〇〇株式会社とか合同会社△△とかといった文字列を自動的に作ってくれるわけです。


return内を記述する前に、このFakerクラスを使うために use で引用しておきます。


use Faker\Generator as Faker;


return の中の記述方法は以下の通りです。


'Corp_nm_f' => $this -> faker -> company


  • カラム 'Corp_nm_f' にダブルアロー関数で$this 以下を入れます

  • $this -> faker でスコープ(difinition() メソッド)外のクラスであるFakerを呼び出し

  • Fakerのプロパティ(メソッド)であるcompanyを実行。companyはFaker PHP ライブラリにアクセスしてランダム企業名を生成します。

  • Fakerのプロパティには()が設定されています。指定する引数がなければ()は省略しても構いません。


Faker のプロパティのうち主なものを表示します。


return の中を記述します。


'Corp_id_f' => $this -> faker -> regexify('[0-9]{10}'),

'Corp_nm_f' => $this -> faker -> company,

'Corp_addr_f' => $this -> faker -> address,

'Corp_tel_f' => $this -> faker -> phoneNumber,

'Corp_dept_f' => $this -> faker -> randomElement($array=[‘総務部‘,’管理部‘,'人事部']),

'Corp_mail_f' => $this -> faker -> email,

'Corp_pw_f' => $this -> faker -> password(8,15),

'Corp_adpw_f' => $this -> faker -> password(8,20)


これでFactoryファイルの中でFakerが定義されました。

次にまた、Seederに戻ってrun()の中身を編集します。


Seederファイルの編集


run() の中に

Laravel7までであれば factory(Corporation::class,15)->create();

Larabal8であれば


Corporation::factory(15)->create();


と記述します。

Corporationモデルを使って15個のFactoryで定義したデータをcreateしてDBに保存しろ、というコマンドです。


Seederの登録


次にこの「CorporationTableSeeder」を「DatabaseSeeder」 に登録します。

DatabaseSeeder.php は database\seeders にデフォルトで準備されているファイルです。


DatabaseSeederは例えばここで作成したCorporationTableSeederのような個別シーダーをcallメソッドで追加的に集めて実行する役割を負っています。

callを使うことでシードファイルが巨大にならないようにするためだそうです。

run() の中に以下のコマンドを記述します。


$this->call(CorporationTableSeeder::class);


Seedを実行する前にいくつかのコマンドを打ちます。

Laravel は内部のキャッシュを強く残す性質があるので、Apacheを再起動しても修正したプログラムが反映してくれないことがよくあります。

そうしたトラブルを事前に回避するためのArtisanコマンドのキャッシュクリア系や最適化のコマンドを実行するわけです。


composer dump-autoload //require文を使わずにパッケージ内の各クラスが相互利用できるパスが生成される


php artisan config:clear   //設定ファイルのキャッシュをクリア


この状態で


php artisan db:seed を打ちます。


コードやcorporationsテーブルに不整合がなければ以下のコメントが表示されてダミーデータが生成されます。


PHP MyAdmin を確認してみます。


所定通りのレコードが生成されていることが確認できます。


以上がSeeder とFactoryを利用したテストデータ作成の実演です。


エラーTIPS


今回は最終的にテストデータの生成に成功しましたが、ここに至るまでに php artisan db:seed で何度かエラーを出してしまいました。


①Column not found: 1054 Unknown column 'updated_at' in 'field list'


Seederで自動的に生成されるcurrent data-time を収める'updated_at'フィールドが見つかりません、と。

テーブルcorporationsを作成する際に実行した2021_07_07_135620_create_corporations_table には'updated_at'フィールドの生成支持はだしていませんでしたので当然こんなフィールドはあるはずがありません。

これは'created_at'フィールドも同じ。

2021_07_07_135620_create_corporations_tableではレコード生成日時を記録するために $table->timestamp('Corp_reg_f') と名前つきの'Corp_reb_f'フィールドの生成指示をだしていたのですが、ここにどうもケチがついたようです。

Migrationのひな型ファイルにはデフォルトで$table->id()->autoIncrement();と $table->timestamps(); の2つのコマンドが用意されていました。

このうち $table->timestamps(); を残してmigration を実行すると自動的に'created_at'と'updated_at'の2つのカラムができるらしいのです。

それを前提にSeederはcurrent data-timeをこの2つのカラムに収容しようとするようなのです。

Seederが'created_at'と'updated_at'を探しに行かないように、という設定方法をネットで探したのですが見当たりませんでしたので、ここはあきらめてPHP MyAdmin で強制的に'created_at'と'updated_at'をカラムとして追加しました。

この2つのカラムはどんなテーブルであっても存在して邪魔になる、というものではありませんので以降Migrationでテーブルを作成する際には $table->timestamps(); を残すことにします。


②String data, right truncated: 1406 Data too long for column 'Corp_pw_f'


これはFakerで生成されたパスワードの文字数が多すぎる、というもの。2021_07_07_135620_create_corporations_table にはCorp_pw_fは(15)と文字数を制限していました。

生成されたパスワードデータが20文字であったので、ここでエラーになったということです。


③Unknown named parameter $max_length


先のエラーを受けてFakerで 'Corp_pw_f' => $this->faker->password(max_length: 15), と書いたのですが、これでNGを食らいました。

ネットで調べてはみたのですが。


いろいろ探して以下のURLにたどり着きました。



ここに

Generate a password, with a given minimum and maximum length. By default, the values 6 and 20 are used for the minimum and maximum respectively.


echo $faker->password();


// 'dE1U[G$n4g%-Eie[]rn[', '-YCc1t|NSh)U&j6Z'


echo $faker->password(2, 6);


// 'GK,M|', '/ZG.'


つまり、パスワードに時数制限を与える引数は(n,m) である、と。

そして、引数指定がない場合は生成されるパスワードは6文字以上20文字以下である、と記載されていましたので、それに従いSeederを実行したところようやくテストデータの作成に成功しました。。

Fakerの各プロパティの書式に関してはいろいろと細かい決まりがあり、かつバージョンもよく変わるので、少し凝ったデータを作りたい場合には以下のようなサイトで書式を確認しましょう。



閲覧数:30回0件のコメント

最新記事

すべて表示

ความคิดเห็น


bottom of page