Laravelのマイグレーション備忘録

## はじめに
マイグレーションからテーブルやカラムを作ったり追加する際に、いちいち調べなおすのが面倒になったので備忘録としてまとめておくことにしました。
LaravelのバージョンはLTSの6系を前提としています。

※追記
Laravel 7系でも動作することを確認しました。

## マイグレーションファイルの作成
`php artisan make:migration create_{テーブル名}_table`コマンドで作成されます。
例えばusersテーブルを新規作成するmigrationファイルを作りたい場合は、以下のようにコマンドを打ちます。

```
php artisan make:migration create_users_table
```

コマンドで指定したファイル名は、そのままPHPのクラス名として作成されるため、複数マイグレーションファイルを作成する場合はファイル名が重複しないように注意してください。

## マイグレーションファイルの編集
#### テーブルの新規作成
さて、`php artisan make:migration`コマンドを実行すると、`database/migrations`フォルダ以下に`2020_06_19_073552_create_users_table.php`というように、ファイルの作成日時+コマンドで指定したファイル名のついたファイルが生成されると思います。
中身を見てみると以下のようになっています。

```create_users_table.php
<?php

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

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

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

テーブルを新規作成したり、カラムを追加・編集したい場合は、`up`メソッドを編集していきます。
今回はシンプルに、ユーザーの[管理番号][ユーザー名][メールアドレス]を管理するテーブルを作成してみます。
create_users_table.phpの```up```メソッドを以下のように編集しましょう。

```create_users_table.php
<?php

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

class CreateUsersTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('users', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->integer('manage_number')->unique(); // 管理番号
            $table->string('name',50); // ユーザー名
            $table->string('mail_address',255); //メールアドレス
            $table->timestamps();
        });
    }

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

上記の編集をしたらマイグレーションを実行します。
マイグレーションの実行は、`php artisan migrate`コマンドを実行します。

```
php artisan migrate
```

コマンド実行後、DBのテーブルを確認してみると、`users`テーブルが作成されています。
もう一つの`migrations`テーブルは、マイグレーションファイルを管理するためのテーブルで、マイグレーションを実行すると自動で作成されます。

```
+-------------------+
| Tables_in_laravel |
+-------------------+
| migrations        |
| users             |
+-------------------+
```

usersテーブルの構成を確認すると、マイグレーションファイルで追記したカラムが作成されています。

```
+---------------+---------------------+------+-----+---------+----------------+
| Field         | Type                | Null | Key | Default | Extra          |
+---------------+---------------------+------+-----+---------+----------------+
| id            | bigint(20) unsigned | NO   | PRI | NULL    | auto_increment |
| manage_number | int(11)             | NO   | UNI | NULL    |                |
| name          | varchar(50)         | NO   |     | NULL    |                |
| mail_address  | varchar(255)        | NO   |     | NULL    |                |
| created_at    | timestamp           | YES  |     | NULL    |                |
| updated_at    | timestamp           | YES  |     | NULL    |                |
+---------------+---------------------+------+-----+---------+----------------+
```

#### カラムを変更する
無事にusersテーブルが作成されました。が、例えばユーザー名を100文字まで増やす必要が出てきた場合はどうすればよいでしょうか。
その場合は、カラムを変更するマイグレーションファイルを生成してマイグレーションを実行すれば解決します。

まずはマイグレーションでカラムの変更が可能になるパッケージをインストールします。

```
composer require doctrine/dbal
```

パッケージインストール後、もう一度`php artisan make:migration`コマンドでマイグレーションファイルを作成しましょう。

```
php artisan make:migration change_name_on_users_table --table=users
```

今回はコマンドに`--tables={テーブル名}`のオプションをつけました。
このオプションを入れておくと、ファイル生成時、スキーマビルダに自動的にオプションで指定したテーブル名を入れてくれるので便利です。

また、マイグレーションファイルは一目で内容が分かるようなファイル名を付けておいた方が後に見直す場合に楽ができます。今回は`name`カラムに対して変更をするので、ファイル名を`change_{修正するカラム名}_on_{テーブル名}_table`としていますが、実際にマイグレーションファイルを生成する場合も、それぞれの内容に適したファイル名を付けることをお勧めします。

上記のコマンドを実行すると、`database/migrations`フォルダ以下に新しく`2020_06_22_013747_change_name_on_users_table.php`の日付け付きのファイルが出来ているはずです。
中身を見てみると以下のようになっています。

```change_name_on_users_table.php
<?php

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

class ChangeNameOnUsersTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::table('users', function (Blueprint $table) {
            //
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::table('users', function (Blueprint $table) {
            //
        });
    }
}
```

`up`メソッドと`down`メソッドの中に、`users`テーブルのスキーマビルダが作成されています。
マイグレーションでカラムを変更するには、`up`メソッド内のスキーマビルダに、変更したいカラムと変更したい内容（今回なら`string`メソッドの第2引数の文字数指定を50から100に変更）を記述し、`change`メソッド(`->change()`)でつなぎます。

```change_name_on_users_table.php
<?php

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

class ChangeNameOnUsersTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::table('users', function (Blueprint $table) {
             $table->string('name',100)->change(); // ユーザー名の最大文字数を50文字→100文字に変更
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::table('users', function (Blueprint $table) {
            $table->string('name',50)->change(); // ユーザー名の最大文字数を100文字→50文字に戻す
        });
    }
}
```

`php artisan migrate`実行後、`users`テーブルの構成を確認すると`name`カラムの文字数が50文字から100文字に変更されました。

```
+---------------+---------------------+------+-----+---------+----------------+
| Field         | Type                | Null | Key | Default | Extra          |
+---------------+---------------------+------+-----+---------+----------------+
| id            | bigint(20) unsigned | NO   | PRI | NULL    | auto_increment |
| manage_number | int(11)             | NO   | UNI | NULL    |                |
| name          | varchar(100)        | NO   |     | NULL    |                |
| mail_address  | varchar(255)        | NO   |     | NULL    |                |
| created_at    | timestamp           | YES  |     | NULL    |                |
| updated_at    | timestamp           | YES  |     | NULL    |                |
+---------------+---------------------+------+-----+---------+----------------+
```

#### カラムを追加する
作成済みのカラムに対して変更を行う方法は分かりました。
次は新しいカラムを追加する方法を説明します。
`php artisan make:migration`コマンドで、性別カラムを追加するマイグレーションファイルを生成します。

```
php artisan make:migration add_sex_on_users_table --table=users
```

生成されたファイルの中身は、カラムを変更する際に作成したファイルとほぼ同じ内容なので割愛します。
カラムを追加するには`up`メソッド内のスキーマビルダに以下のように記述します。

```add_sex_on_users_table.php
<?php

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

class AddSexOnUsersTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::table('users', function (Blueprint $table) {
            $table->boolean('sex'); // 性別カラムを追加
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::table('users', function (Blueprint $table) {
            $table->dropColumn('sex'); // 性別カラムを削除
        });
    }
}
```

``php artisan migrate``を実行すると、性別カラムが追加されました。

```
+---------------+---------------------+------+-----+---------+----------------+
| Field         | Type                | Null | Key | Default | Extra          |
+---------------+---------------------+------+-----+---------+----------------+
| id            | bigint(20) unsigned | NO   | PRI | NULL    | auto_increment |
| manage_number | int(11)             | NO   | UNI | NULL    |                |
| name          | varchar(100)        | NO   |     | NULL    |                |
| mail_address  | varchar(255)        | NO   |     | NULL    |                |
| created_at    | timestamp           | YES  |     | NULL    |                |
| updated_at    | timestamp           | YES  |     | NULL    |                |
| sex           | tinyint(1)          | NO   |     | NULL    |                |
+---------------+---------------------+------+-----+---------+----------------+
```


カラムの追加は、`up`メソッドのスキーマビルダに追加したいカラムを指定して記述することで追加することができます。


#### その他のカラム操作
文字数を増やしたり、カラムを追加する以外にもカラムを操作することができます。
以下には利用機会が多そうなカラム操作の記述方法を記載しておきます。

**カラム名変更(renameColumn)**

```
 $table->renameColumn('name', 'name_sei');
```

**指定のカラムの上にカラムを追加(before)**

```
$table->string('tel_number', 100)->before('mail_address ');
```

**指定のカラムの下にカラムを追加(after)**

```
$table->string('name_mei', 100)->after('name_sei');
```

**カラムを削除(dropColumn)**

```
$table->dropColumn('name_mei');
```

**nullを許容(nullable)**

```
$table->string('tel_number', 100)->nullable()->change();
```

**デフォルト値を指定(default)**

```
$table->string('tel_number', 100)->nullable()->default(null)->change();
```

カラムの操作方法は上記以外にもまだまだたくさんあります。
詳しくは[公式マニュアル](https://readouble.com/laravel/6.x/ja/migrations.html)にも書いてあるので、一読することをお勧めします。

#### ロールバック
マイグレーションで作成したテーブルやカラムは、ロールバックすることができます。
ロールバックするには以下のコマンドを実行します。

```
php artisan migrate:rollback
```

このコマンドを実行すると、**同時に**実行した最後のマイグレーションをまとめて元に戻します。
今回は最後に実行した性別カラムを追加するマイグレーションがロールバックされ、性別カラムが削除されました。

```
+---------------+---------------------+------+-----+---------+----------------+
| Field         | Type                | Null | Key | Default | Extra          |
+---------------+---------------------+------+-----+---------+----------------+
| id            | bigint(20) unsigned | NO   | PRI | NULL    | auto_increment |
| manage_number | int(11)             | NO   | UNI | NULL    |                |
| name          | varchar(100)        | NO   |     | NULL    |                |
| mail_address  | varchar(255)        | NO   |     | NULL    |                |
| created_at    | timestamp           | YES  |     | NULL    |                |
| updated_at    | timestamp           | YES  |     | NULL    |                |
+---------------+---------------------+------+-----+---------+----------------+
```

ロールバックは、マイグレーションファイルの`down`メソッドのスキーマビルダに記述した処理が実行されます。
最後に実行したマイグレーションファイルの`down`メソッドの記述を確認してみましょう。

```add_sex_on_users_table.php
    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::table('users', function (Blueprint $table) {
            $table->dropColumn('sex'); // 性別カラムを削除
        });
    }
```

`down`メソッドのスキーマビルダに記述した性別カラム削除の処理が実行されたことが分かると思います。
ロールバックする位置を指定したい場合は、ロールバックコマンドのオプションに`--step={ロールバックする個数}`を指定することにより、指定した個数分のマイグレーションファイルまでロールバックする事が出来ます。

実際に、名前カラムの文字数を50文字に戻すところまでロールバックしてみましょう。
名前カラムの文字数を増やしたマイグレーションファイルの`down`メソッドには以下の記述がしてありました。


```change_name_on_users_table.php
    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::table('users', function (Blueprint $table) {
            $table->string('name',50)->change(); // ユーザー名の最大文字数を100文字→50文字に戻す
        });
    }
```

ロールバックする位置を指定してコマンドを実行します。

```
php artisan migrate:rollback --step=2
```

ロールバック実行後、`users`テーブルを確認すると、名前カラムの文字数が50文字に戻っていることが確認できます。

```
+---------------+---------------------+------+-----+---------+----------------+
| Field         | Type                | Null | Key | Default | Extra          |
+---------------+---------------------+------+-----+---------+----------------+
| id            | bigint(20) unsigned | NO   | PRI | NULL    | auto_increment |
| manage_number | int(11)             | NO   | UNI | NULL    |                |
| name          | varchar(50)         | NO   |     | NULL    |                |
| mail_address  | varchar(255)        | NO   |     | NULL    |                |
| created_at    | timestamp           | YES  |     | NULL    |                |
| updated_at    | timestamp           | YES  |     | NULL    |                |
+---------------+---------------------+------+-----+---------+----------------+
```

ちなみに、ロールバックしたい位置を指定する場合は、`migrations`テーブルを確認すると比較的楽です。

```
+----+----------------------------------------------+-------+
| id | migration                                    | batch |
+----+----------------------------------------------+-------+
|  1 | 2020_06_19_073552_create_users_table         |     1 |
|  2 | 2020_06_22_013747_change_name_on_users_table |     2 |
|  4 | 2020_06_22_053853_add_sex_on_users_table     |     3 |
+----+----------------------------------------------+-------+
```

## 最後に
Laravelのマイグレーションは、複数人で開発をしている際、無駄なSQLファイルのやり取りをなくし環境を同一化できたり、gitなどでマイグレーションファイル自体を簡単に管理することができるおすすめのできる機能です。
Laravel自体を使う上でも有用な機能ですので、参考にしていただけたなら幸いです。