【Laravel6】ユーザー招待機能の詳細設計と実装(2)マイグレーションファイルからのテーブル作成

# はじめに

ユーザー招待機能の詳細設計と実装(2) マイグレーションファイルからのテーブル作成 について投稿します。

Web業界実務未経験での転職活動用にポートフォリオとしてはじめて作成したWebアプリ開発のオリジナルの機能として **家族ユーザー招待機能** を実装したときのものです。
※ 作成したポートフォリオは、絵本を読み聞かせしたことの記録・管理を、家族と共有できるWebアプリケーションです（作成期間は、2021年2月末〜7月）

https://qiita.com/ryamate/items/c3b4f63f8d94ab090bf8

## 投稿内容（全5回）

本連載は以下の順番で投稿します。

- **[招待ユーザー機能の概要と基本設計](https://qiita.com/ryamate/items/751b06dc95ab9b24e361)**
- **招待ユーザー機能の詳細設計と実装**
    - [(1) 招待メール送信フォーム](https://qiita.com/ryamate/items/a1d0a5b1db9d11a69671)
    - **(2) マイグレーションファイルからのテーブル作成**
    - [(3) 招待メール送信処理](https://qiita.com/ryamate/items/39a95e504b229edd5d3b)
    - [(4) 招待メールのテンプレート](https://qiita.com/ryamate/items/9392ba2a6e6351544e7b)
    - [(5) ユーザー登録フォームと登録処理](https://qiita.com/ryamate/items/57a94656134870d31edb)

今回は、**ユーザー招待機能の詳細設計と実装(2) DBのテーブル** についてです。 Laravel のマイグレーション機能を使って、データベースに invites テーブルを作成します。

## 目次

以下、本記事の目次です。

1. [マイグレーションファイルの作成](#1-マイグレーションファイルの作成)
1. [マイグレーションファイルの編集](#2-マイグレーションファイルの編集)
1. [マイグレーションの実行](#3-マイグレーションの実行)
1. [テーブルの作成状況の確認](#4-テーブルの作成状況の確認)

## 使用技術、サービスなど

- PHP 7.4.13
- Laravel 6.20.20
- MySQL 8.0.23
- [MailHog](https://github.com/mailhog/MailHog)（開発者向けのメールテストツール、開発環境）

## マイグレーションとは

マイグレーションとは、データベースにテーブルを作成したり、既存のテーブルにカラム(項目)を追加したりといった、データベース内の定義を変更する機能です。

Laravel を使ってデータベースにテーブルを作成するには、まずマイグレーションファイルを作成する必要があります。

https://readouble.com/laravel/6.x/ja/migrations.html

家族ユーザー招待に必要なデータを保存するために、**Invites** テーブルを用意します。

テーブルを必要とする理由は、どの家族（`family_id`）が、誰（`email`）を招待したかと、その招待 URL に利用するトークン（`token`）を保存するためです。

# 1. マイグレーションファイルの作成

以下のコマンドを実行して、マイグレーションファイルを作成します。

```bash
docker-compose exec app php artisan make:migration create_invites_table --create=invites
```

コマンドを実行すると、**database/migrations/** ディレクトリに、以下のファイルが作成されます。

```php:作成：database/migrations/2021_06_09_180935_create_invites_table.php
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateInvitesTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('invites', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('invites');
    }
}
```

# 2. マイグレーションファイルの編集

家族ユーザー招待機能で利用するテーブルの定義を確認して、コマンド実行で作成されたマイグレーションファイルを編集します。

## 2-1. テーブル定義の確認

家族ユーザー招待機能で利用するテーブルの定義は以下のとおりです。

| カラム名 | データ型 | 役割・備考 |
| --- | --- | --- |
| id | INTEGER | 招待メール発行を管理するID |
| family_id | INTEGER | 招待した側のファミリーID |
| email | VARCHAR(255) | 招待された側のメールアドレス |
| token | VARCHAR(16) | 招待メールのトークン |
| created_at | TIMESTAMP | 作成日時 |
| updated_at | TIMESTAMP | 更新日時 |

どの家族（`family_id`）が、誰（`email`）を招待したかと、その招待 URL に利用するトークン（`token`）を保存します。

## 2-2. マイグレーションファイルの編集

マイグレーションファイルを編集します。

```php:編集：database/migrations/2021_06_09_180935_create_invites_table.php
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateInvitesTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('invites', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->unsignedBigInteger('family_id');
            $table->string('email');
            $table->string('token', 16)->unique();
            $table->timestamps();

            $table->foreign('family_id')
                ->references('id')
                ->on('families');
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('invites');
    }
}
```

マイグレーションファイルでカラムを定義するには、 `$table->カラムの属性('カラム名');` と記述します。

マイグレーションを実行すると、このマイグレーションファイルが使用され、設定したカラムを持った invites テーブルが作成されます。

## 2-3. 参考

### 使用できるカラムタイプ

使用できるさまざまなカラムタイプがある。

| コマンド | 説明 |
| --- | --- |
| $table->bigIncrements('id'); | 符号なしBIGINTを使用した自動増分ID（主キー） |
| $table->unsignedBigInteger('votes'); | 符号なしBIGINTカラム |
| $table->string('name', 100); | 文字長を指定したVARCHARカラム |
| $table->timestamps(0); | 有効（全体）桁数指定でNULL値可能なcreated_atとupdated_atカラム追加 |

https://readouble.com/laravel/6.x/ja/migrations.html#creating-columns

### unique メソッド

`unique`メソッドを使うことで、そのカラムにユニーク制約を付ける。ユニーク制約とは、テーブル内で他のレコードと同じ値を重複させないという制約。

invites テーブルについては、 `token` を重複させないため、ユニーク制約を追加している。

### 外部キー制約

`family_id` については、カラムを作成するだけでなく、外部キー制約を付けている。

```php
$table->foreign('family_id')
    ->references('id')
    ->on('families');
```

上記は、「 **invites** テーブルの `family_id` カラムは、 **families** テーブルの`id`カラムを参照すること」という制約になる。

外部キー制約を付けることで、「発行された招待用トークンがどの家族への招待でもない」という状態を作れないようにしている。

# 3. マイグレーションの実行

以下のコマンドで、マイグレーションを実行します。

```bash
docker-compose exec app php artisan migrate
```

https://readouble.com/laravel/6.x/ja/migrations.html#running-migrations

# 4. テーブルの作成状況の確認

以下コマンドを実行して、テーブルの作成状況を確認します。

```bash
docker-compose exec db bash -c 'mysql -u $MYSQL_USER -p$MYSQL_PASSWORD $MYSQL_DATABASE'
```

※ 以下の環境を利用している場合のコマンドです

https://qiita.com/ucan-lab/items/5fc1281cd8076c8ac9f4#dbコンテナのmysqlに接続する

```bash:実行時ログ
# r_yamate @ mbp in ~/Documents/code/Yonde-app on git:doc/mod_erd x [7:23:52]
$ docker-compose exec db bash -c 'mysql -u $MYSQL_USER -p$MYSQL_PASSWORD $MYSQL_DATABASE'
mysql: [Warning] Using a password on the command line interface can be insecure.
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 8
Server version: 8.0.29 MySQL Community Server - GPL

Copyright (c) 2000, 2022, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql>
```

```bash
mysql> SHOW COLUMNS FROM invites;
+------------+-----------------+------+-----+---------+----------------+
| Field      | Type            | Null | Key | Default | Extra          |
+------------+-----------------+------+-----+---------+----------------+
| id         | bigint unsigned | NO   | PRI | NULL    | auto_increment |
| family_id  | bigint unsigned | NO   | MUL | NULL    |                |
| email      | varchar(255)    | NO   |     | NULL    |                |
| token      | varchar(16)     | NO   | UNI | NULL    |                |
| created_at | timestamp       | YES  |     | NULL    |                |
| updated_at | timestamp       | YES  |     | NULL    |                |
+------------+-----------------+------+-----+---------+----------------+
6 rows in set (0.01 sec)
```

# おわりに

今回は、**ユーザー招待機能の詳細設計と実装(2) マイグレーションファイルからのテーブル作成** についてでした。
次回は、**[(3) 招待メール送信処理](https://qiita.com/ryamate/items/39a95e504b229edd5d3b)** についてです。

ありがとうございました。

## 参考

https://qiita.com/ucan-lab/items/5fc1281cd8076c8ac9f4#dbコンテナのmysqlに接続する

https://github.com/ucan-lab/docker-laravel