今回はLaravel Sailを使用します。SailはアプリケーションのDockerコンテナ内でArtisanコマンドを実行します。
コマンドを書く際に
./vendor bin sailをsailに省略しています。
今回のハンズオンのリポジトリは以下です。
1. 背景
業務でLaravelを使っているので勉強のために書きます。
今回はmigrationでテーブルを作成、Seederで作成後のテーブルにサンプルデータの挿入をします。
2. migrationとは
SQLを使わずにDBを管理できる仕組みです。
以下の流れでTableを作成、削除、編集できます。
- migrationファイルを作成
- migrationを実行
3. migrationで作成するテーブルのER図
3.1. employees(従業員テーブル)
従業員の情報を保持します。
Column | Type | Description |
---|---|---|
employee_id | INT | 従業員ID(主キー) |
name | VARCHAR(50) | 名前 |
position | VARCHAR(50) | 役職 |
department_id | INT | 部門ID(外部キー) |
3.2. departments(部門テーブル)
各部門の情報を保持します。
Column | Type | Description |
---|---|---|
department_id | INT | 部門ID(主キー) |
department_name | VARCHAR(50) | 部門名 |
3.3. projects(プロジェクトテーブル)
プロジェクトの情報を保持します。
Column | Type | Description |
---|---|---|
project_id | INT | プロジェクトID(主キー) |
project_name | VARCHAR(50) | プロジェクト名 |
department_id | INT | 部門ID(外部キー) |
3.4. employee_project(従業員とプロジェクトの関連テーブル)
従業員が参加しているプロジェクトの情報を保持します。
Column | Type | Description |
---|---|---|
employee_id | INT | 従業員ID(外部キー) |
project_id | INT | プロジェクトID(外部キー) |
4. migrationファイルを作成する
sail artisan make:migration [アクション名]_[テーブル名]_table
マイグレーションファイル名は記法に決まりはないですが、上のように書くと良いそうです。
sail artisan make:migration create_departments_table
以下のようなファイルが作成されます。
[タイムスタンプ]_create_departments_table.php
タイムスタンプが小さいものから先にmigrationが実行されます。
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('departments', function (Blueprint $table) {
$table->id();
$table->string('name', 50);
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('departments');
}
};
-
$table->id()
bigIncrementsのエイリアスです。
作成されるカラムはUNSIGNED BIGINT型の主キーです。 -
$table->string('name', 50)
VARCHAR型のカラムで、カラム名はnameです。
sail artisan make:migration create_employees_table
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('employees', function (Blueprint $table) {
$table->id();
$table->string('name', 50);
$table->string('position', 50);
$table->unsignedBigInteger('department_id');
$table->foreign('department_id')->references('id')->on('departments')->onDelete('cascade');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('employees');
}
};
~~~~~~~~~~~~~
$table->unsignedBigInteger('department_id');
$table->foreign('department_id')->references('id')->on('departments')->onDelete('cascade');
~~~~~~~~~~~~~
department_idは外部参照キーで、departmentsテーブルのidです。
departmentsテーブルの該当のidのレコードが削除されたときに、projectsテーブルでdepartmentsテーブルの削除されたidを参照していたレコードも自動的に削除されます。
docにもありましたが以下のように簡潔に書き直せるのでこちらの方が良いですね。
$table->foreignId('department_id')->constrained('departments')->onDelete('cascade');
sail artisan make:migration create_projectss_table
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('projects', function (Blueprint $table) {
$table->id();
$table->string('name', 50);
$table->unsignedBigInteger('department_id');
$table->foreign('department_id')->references('id')->on('departments')->onDelete('cascade');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('projects');
}
};
sail artisan make:migration create_employee_project_table
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('employee_project', function (Blueprint $table) {
$table->unsignedBigInteger('employee_id');
$table->foreign('employee_id')->references('id')->on('employees')->onDelete('cascade');
$table->unsignedBigInteger('project_id');
$table->foreign('project_id')->references('id')->on('projects')->onDelete('cascade');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('employee_project');
}
};
5. migratinonを実行する
sail artisan migrate
新しくdepartments,employee_project,employees,projectsが追加されています。
mysql> show tables;
+-----------------------+
| Tables_in_laravel |
+-----------------------+
| cache |
| cache_locks |
| departments |
| employee_project |
| employees |
| failed_jobs |
| job_batches |
| jobs |
| migrations |
| password_reset_tokens |
| projects |
| sessions |
| users |
+-----------------------+
13 rows in set (0.00 sec)
次にテーブルにサンプルデータを挿入します。
6. サンプルデータ
6.1. employees テーブル
id | name | position | department_id |
---|---|---|---|
1 | Alice | Manager | 1 |
2 | Bob | Developer | 1 |
3 | Charlie | Developer | 2 |
4 | David | Analyst | 2 |
6.2. departments テーブル
id | department_name |
---|---|
1 | Engineering |
2 | Research |
6.3. projects テーブル
id | project_name | department_id |
---|---|---|
1 | Project A | 1 |
2 | Project B | 1 |
3 | Project C | 2 |
6.4. employee_project テーブル
employee_id | project_id |
---|---|
1 | 1 |
2 | 1 |
2 | 2 |
3 | 3 |
4 | 3 |
7. SeederでTableにサンプルデータを挿入する
sail artisan make:seeder EmployeeDepartmentProjectSeeder
<?php
namespace Database\Seeders;
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
class EmployeeDepartmentProjectSeeder extends Seeder
{
/**
* Run the database seeds.
*/
public function run(): void
{
// departmentsテーブルにデータを挿入
DB::table('departments')->insert([
['name' => 'Engineering'],
['name' => 'Research'],
]);
// employeesテーブルにデータを挿入
DB::table('employees')->insert([
['name' => 'Alice', 'position' => 'Manager', 'department_id' => 1],
['name' => 'Bob', 'position' => 'Developer', 'department_id' => 1],
['name' => 'Charlie', 'position' => 'Developer', 'department_id' => 2],
['name' => 'David', 'position' => 'Analyst', 'department_id' => 2],
]);
// projectsテーブルにデータを挿入
DB::table('projects')->insert([
['name' => 'Project A', 'department_id' => 1],
['name' => 'Project B', 'department_id' => 1],
['name' => 'Project C', 'department_id' => 2],
]);
// employee_projectテーブルにデータを挿入
DB::table('employee_project')->insert([
['employee_id' => 1, 'project_id' => 1],
['employee_id' => 2, 'project_id' => 1],
['employee_id' => 2, 'project_id' => 2],
['employee_id' => 3, 'project_id' => 3],
['employee_id' => 4, 'project_id' => 3],
]);
}
}
<?php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
class DatabaseSeeder extends Seeder
{
/**
* Seed the application's database.
*/
public function run(): void
{
$this->call(EmployeeDepartmentProjectSeeder::class);
}
}
サンプルデータの挿入を実行します
sail artisan db:seed
データが挿入されています。
mysql> select * from projects;
+----+-----------+---------------+------------+------------+
| id | name | department_id | created_at | updated_at |
+----+-----------+---------------+------------+------------+
| 1 | Project A | 1 | NULL | NULL |
| 2 | Project B | 1 | NULL | NULL |
| 3 | Project C | 2 | NULL | NULL |
+----+-----------+---------------+------------+------------+
3 rows in set (0.00 sec)
8. 参考
9. 最後に
- documentを読みたいと思います
- 次回はModel、Controller、Viewを作成し、クエリの結果を表示して業務アプリに近いものを作ります