laravel7で、seeder + factory + fakerを使ってサンプル掲示板レコードを作る。user, post, replyテーブルに予めレコードを挿入してみた。
// 用語
seeder(種まき機) = 各テーブルのレコードを自動生成する。
factory(工場) = 同じレコードを指定された数だけ大量生産する。fakerを使えばランダム値のレコード生成できる
faker(偽物屋) = 名前やメアドなどランダム値を生成。日本語は名前や住所など限定的。realtextは日本語文章の断片を取得する
// 何をやるのか?
0, サンプル掲示板を作る。user, post, replyテーブルに予めレコードを挿入しておきたい。
1, 人間的発想だと、親user -> 子post -> 孫replyという順番で生成したいが
親reply(->子user) -> 子post -> 孫userという順番で生成した方がリレーション的に簡単。
2, userテーブルは最初からあるので、投稿テーブルと返信テーブルを作成
1 2 |
php artisan make:model Post --all php artisan make:model Reply --all |
3, database/seeds/DatabaseSeeder.phpで、どのSeederを使うか指定する。親となるReplySeederを指定
1 2 3 |
public function run() { $this->call(ReplySeeder::class); } |
4, database/seeds/ReplySeeder.phpでは、生成するモデル(App/Reply)とレコード数を指定。
1 2 3 |
public function run(){ factory(App\Reply::class, 10)->create(); } |
5, database/factories/ReplyFactory.phpで、生成するレコードの値を指定。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<?php use App\Reply; use Faker\Generator as Faker; $factory->define(Reply::class, function (Faker $faker) { return [ 'post_id' => function(){ //Postインスタンスを作成する際に、リレーションするUserインスタンスも生成する return factory(App\Post::class)->create()->id; }, 'user_id' => function(){ //Postインスタンスを作成する際に、リレーションするUserインスタンスも生成する return factory(App\User::class)->create()->id; }, //'body' => $faker->realText, 'body' => $faker->randomElement(['無理です', '分かりました。なんとかしましょう!']) , ]; }); |
6, database/factories/PostFactory.phpで、投稿レコードの値を指定。
fakerの日本語文章だと、意味不明なので、適当な日本語を自作してランダム出力する。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
<?php use App\Post; use Faker\Generator as Faker; $factory->define(Post::class, function (Faker $faker) { return [ 'user_id' => function(){ //Postインスタンスを作成する際に、リレーションするUserインスタンスも生成する return factory(App\User::class)->create()->id; }, 'title' => $faker->name . 'について', // 'body' => $faker->realText, 'body' => $faker->randomElement([ '半年も独学でプログラミングの勉強をしているのですが、作りたいプログラミングがありません。', '誰か、どうにかして!', 'セクハラされました。どうすればいいんでしょうか?', '朝、起きるのが辛いです…。', '夏に向けてダイエットすべきでしょうか?', '子供の好き嫌いが激しくてフリカケご飯しか食べません。どうすればいいんでしょうか?', ]) , ]; }); |
※userのfactoryは最初からある。
7, php artisan migrate:fresh –seed でテーブルとレコードを自動生成する。
親子関係のあるテーブルでも、自動生成出来るのは知っていたけど、親子孫の順番を逆にした方が関連性を気にせずにバンバン作れて良い気もするね。
実際に使う時は、PostモデルにhasmanyでReplyを保持させるのが楽でいい。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
mysql> select title, posts.body, replies.body from posts left join replies on posts.id = replies.post_id; +---------------------------------+--------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------+ | title | body | body | +---------------------------------+--------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------+ | 佐々木 あすかについて | 誰か、どうにかして! | 無理です | | 高橋 桃子について | セクハラされました。どうすればいいんでしょうか? | 無理です | | 吉本 直樹について | 朝、起きるのが辛いです…。 | 分かりました。なんとかしましょう! | | 廣川 篤司について | 誰か、どうにかして! | 分かりました。なんとかしましょう! | | 木村 和也について | 夏に向けてダイエットすべきでしょうか? | 無理です | | 吉田 幹について | 半年も独学でプログラミングの勉強をしているのですが、作りたいプログラミングがありません。 | 分かりました。なんとかしましょう! | | 近藤 加奈について | 誰か、どうにかして! | 無理です | | 村山 七夏について | 半年も独学でプログラミングの勉強をしているのですが、作りたいプログラミングがありません。 | 無理です | | 渚 零について | 朝、起きるのが辛いです…。 | 分かりました。なんとかしましょう! | | 高橋 真綾について | 夏に向けてダイエットすべきでしょうか? | 無理です | +---------------------------------+--------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------+ 10 rows in set (0.00 sec) |
8, 人間的感覚に従ってuser->post->replyの順に生成すると、こうなる。
コーディング的には、ややこしくなるな・・・。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
<?php use Illuminate\Database\Seeder; use Faker\Generator as Faker; class UserSeeder extends Seeder { public function run() { $user_num = 4; // まずユーザー作成 factory(App\User::class, $user_num)->create() // 作成されたそれぞれのユーザに対して ->each(function ($user) { // 1つ投稿記事を生成する。値はfactoryの上書き出来る $user->posts()->save(factory(App\Post::class)->make([ 'user_id' => $user->id, 'title' => '課題その'. $user->id, 'body' => 'こういう問題がある。その'. $user->id, // for-for文なので、最初の方が段々と重複していく ]))->each(function ($post) { $post->replies()->save(factory(App\Reply::class)->make([ 'user_id' => $post->user_id, 'post_id' => $post->id, 'body' => '返信の本文'. $post->id, ])); }); }); } } |