お久しぶりです。福岡拠点の香月です。
今回はシーダーです。
作成したテーブルに初期データやテストデータをを投入するときに使います。
前回からテーブルを2つ「subjects」「students」を追加しています。
1 2 |
# php artisan make:model Subject -m # php artisan make:model Student -m |
マイグレーションファイルでフィールドを定義して
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 30 31 32 |
<?php use Illuminate\Support\Facades\Schema; use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; class CreateSubjectsTable extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('subjects', function (Blueprint $table) { $table->increments('id'); $table->string('name', 255); $table->timestamps(); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::dropIfExists('subjects'); } } |
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 30 31 32 33 34 |
<?php use Illuminate\Support\Facades\Schema; use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; class CreateStudentsTable extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('students', function (Blueprint $table) { $table->increments('id'); $table->string('family_name', 255); $table->string('first_name', 255); $table->timestamp('birth_day'); $table->timestamps(); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::dropIfExists('students'); } } |
マイグレーション
1 2 3 4 5 |
# php artisan migrate Migrating: 2019_02_16_130627_create_students_table Migrated: 2019_02_16_130627_create_students_table Migrating: 2019_02_16_131312_create_subjects_table Migrated: 2019_02_16_131312_create_subjects_table |
これでテーブルが追加されました。
ではここに初期データを投入しましょう。Subjectテーブルは科目、Studentテーブルは生徒、Scoreテーブルは点数です。
まずはシーダーファイルを作成するために、make:seederコマンドを実行します。
1 2 3 |
# php artisan make:seeder SubjectSeeder # php artisan make:seeder StudentSeeder # php artisan make:seeder ScoreSeeder |
すると、Laravelプロジェクトフォルダのdatabase/seedsフォルダにファイルSubjectSeeder.php、StudentSeeder.php、ScoreSeeder.phpが作成されます。
まずはSubjectシーダー。
作成されたシーダークラスファイルには run() メソッドが用意されています。シーダーが呼び出されるとこのメソッドが実行されるようになっているため、ここにデータ投入用プログラムを記述します。
上にuse App\Subject; を追加して、Subject Eloquentモデルを使えるようにするのを忘れずに。
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 |
<?php use Illuminate\Database\Seeder; use App\Subject; class SubjectSeeder extends Seeder { /** * Run the database seeds. * * @return void */ public function run() { Subject::truncate(); $seeds = [ '国語', '算数', '理科', '社会' ]; foreach ($seeds as $seed) { $subject = new Subject; $subject->name = $seed; $subject->save(); } } } |
Subjectクラスのインスタンスを作成して、フィールドに値を設定し、save()メソッドを呼ぶことでレコードが追加されます。
このプログラムでは$seeds配列の1つ1つが1レコードとなるようなプログラムになっています。
続いてStudentシーダー。こちらはモデルファクトリを使って、フィールド値をランダム生成します。フィールド値には日本語を使いたいので、config\app.phpを次のように修正。
1 2 |
//'faker_locale' => 'en_US', 'faker_locale' => 'ja_JP', |
次にファクトリコード用のファイルを作成します。
1 |
# php artisan make:factory StudentFactory --model=Student |
作成したファイルdatabase\factories\StudentFactory.phpを次のようにします。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<?php use Faker\Generator as Faker; $factory->define(App\Student::class, function (Faker $faker) { $min = strtotime('2011-04-02'); $max = strtotime('2012-04-01'); return [ 'family_name' => $faker->lastName, 'first_name' => $faker->firstName, 'birth_day' => date('Y-m-d', rand($min, $max)), ]; }); |
$factory->define()の第二引数のクロージャで、Studentレコード1件分の情報としてフィールド名(キー)と値(バリュー)の配列を返すようになっています。$faker->lastName、$faker->firstName部分がランダム生成の部分。これ以外にもcity、phoneNumber、wordなどいろいろ使えます。便利。誕生日は2011/04/02~2012/04/01までの1年間でランダムに生成されるようにしました。
そしてdatabase\seeds\StudentSeeder.phpです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
<?php use Illuminate\Database\Seeder; use App\Student; class StudentSeeder extends Seeder { /** * Run the database seeds. * * @return void */ public function run() { Student::truncate(); factory(Student::class, 20)->create(); } } |
モデルファクトリを使って20個のエントリを簡単に作成できます。
database\seeds\ScoreSeeder.phpはこう。
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 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
<?php use Illuminate\Database\Seeder; use App\Score; use App\Student; use App\Subject; class ScoreSeeder extends Seeder { /** * Run the database seeds. * * @return void */ public function run() { Score::truncate(); $subjects = Subject::all(); $students = Student::all(); $days = [ '2018-05-30', '2018-07-05', '2018-10-28', '2018-12-15', '2019-02-12', '2019-03-10', ]; foreach ($days as $day) { foreach ($subjects as $subject) { foreach ($students as $student) { $score = new Score; $score->student_id = $student->id; $score->subject_id = $subject->id; $score->exam_day = $day; $score->score = rand(50,100); $score->save(); } } } } } |
作成したSubject、Studentの全レコードを取得し、ループで回しながら作成していきます。
プログラムができたらシーダーを実行しましょう。実行コマンドはdb:seedです。
実行するクラス名を–class=オプションで指定します。
1 2 3 |
# php artisan db:seed --class=SubjectSeeder # php artisan db:seed --class=StudentSeeder # php artisan db:seed --class=ScoreSeeder |
これは1つずつ実行するコマンドとなりますが、まとめて実行したい場合は最初から用意されているDatabaseSeederクラスを利用するとよいでしょう。
database\seeds\DatabaseSeeder.phpファイル内の run() メソッドからまとめて処理したいクラスを指定して、
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<?php use Illuminate\Database\Seeder; class DatabaseSeeder extends Seeder { /** * Seed the application's database. * * @return void */ public function run() { $this->call(SubjectSeeder::class); $this->call(StudentSeeder::class); $this->call(ScoreSeeder::class); } } |
db:seedコマンドをオプションなしで実行します。
1 2 3 4 5 |
# php artisan db:seed Seeding: SubjectSeeder Seeding: StudentSeeder Seeding: ScoreSeeder Database seeding completed successfully. |
これでデータ投入が完了しました。