1. Home
  2. PHP
  3. Laravel
  4. LaravelのMigration(マイグレーション)でテーブルのカラムを追加・変更・削除する

LaravelのMigration(マイグレーション)でテーブルのカラムを追加・変更・削除する

  • 公開日
  • 更新日
  • カテゴリ:Laravel
  • タグ:PHP,Laravel,migration,SchemaBuilder
LaravelのMigration(マイグレーション)でテーブルのカラムを追加・変更・削除する

今回は Laravel の migration(マイグレーション)で、作成したテーブルに対して、カラムの追加、変更、削除などを行います。

Contents

  1. 開発環境
  2. マイグレーションでデータベースを管理し開発を行う
  3. カラム変更マイグレーションの準備
  4. カラム変更用マイグレーションファイルの生成
  5. マイグレーションファイルの確認とスキーマビルダ記述
  6. マイグレーションを実行してカラムを追加する
  7. ロールバックを行う

開発環境

前回は同機能でテーブルの作成までを行いました。マイグレーションについての基本や再現環境等含め、前回の続きとして進めていきますので、必要な場合はそちらを確認してください。
previous:Laravel のマイグレーション&スキーマビルダで DB のテーブルやカラムを作成する

尚、Laravel のバージョンに関しては 5.7/5.6/5.5/5.4/5.3 で動作確認済みです。

マイグレーションでデータベースを管理し開発を行う

開発を続けていくと、テーブルにカラムを追加する必要があったり、初期で決めたカラムの定義を変更する(カラム名の変更・最大文字長の変更など)必要も出てくる場合があります。その場合にも、マイグレーションで構築が可能です。

また、その場合は、先ほど作ったファイルを編集するのではなく、新たにマイグレーションファイルを作成し、都度スキーマビルダで記述していきます。

元のファイルを修正するのではなく、何故わざわざ新しくマイグレーションファイルを作成するのかというと、**現在投入しているデータベースのデータをそのままにカラム追加を行える。**という事に利点があります。

そもそもマイグレーションとは、データベースのバージョン管理のような役割があり、一度マイグレーションを実行し構築したテーブルに関して改めて同じマイグレーションを実行する場合は、そのテーブルを一度削除(drop)してから再構築するという流れになっています。(ロールバックからの、マイグレーション再実行。という手順)

という事は、それまで入っていたデータ自体は一緒に消失するという事になりますので、またデータを入れ直さなければなりません。これは大きな手間になります。

また、これが1人で開発を行っている場合はまだ良いですが、もしチームで開発をしていて、各々、データのインサートをテストで行っていた場合などは、各々、入っているデータの内容は異なるはずです。にも関わらず、誰かの開発でカラム追加や変更が発生したとしたら、チーム全員がテストデータを入れ直さなければならない状況が生まれてしまうからです。しかも機能開発時にプログラムテストでインサートされたデータなんて、初期投入用データには入っているはずがありません(都度作るなら別ですが)

という事なので、カラム変更や追加が発生した際には、新たにマイグレーションを作成し、そこへ記述していきます。

カラム変更マイグレーションの準備

実は Laravel では、デフォルトのままではカラム変更のマイグレーションは行えません。新たにパッケージを導入する必要があります。
(とはいえ公式のアナウンスなので安心の手順です)

Laravel ルートディレクトリへ移動して、「doctrine/dbal 」を依存パッケージとして追加します。

# Laravel のルートディレクトリへ移動
cd /path/to/laravel

# doctrine/dbal パッケージの導入
composer require doctrine/dbal

# 実行結果
[demo@localhost laravel]$ composer require doctrine/dbal
Using version ^2.8 for doctrine/dbal
./composer.json has been updated
Loading composer repositories with package information
Updating dependencies (including require-dev)
Package operations: 3 installs, 0 updates, 0 removals
  - Installing doctrine/event-manager (v1.0.0): Loading from cache
  - Installing doctrine/cache (v1.8.0): Downloading (100%)         
  - Installing doctrine/dbal (v2.8.0): Loading from cache
doctrine/cache suggests installing alcaeus/mongo-php-adapter (Required to use legacy MongoDB driver)
Writing lock file
Generating optimized autoload files
> Illuminate\Foundation\ComposerScripts::postAutoloadDump
> @php artisan package:discover
Discovered Package: beyondcode/laravel-dump-server
Discovered Package: fideloper/proxy
Discovered Package: laravel/tinker
Discovered Package: nesbot/carbon
Discovered Package: nunomaduro/collision
Package manifest generated successfully.

実行結果については、導入した時期によってバージョンの違いなどが出ると思うので細かい事は抜きにして、エラーを吐いていなければとりあえず OK です。

ここで一度、laravel/composer.json を開いて doctrine/dbal が導入されたかを確認します。

"require": {
    "php": "^7.1.3",
    "doctrine/dbal": "^2.8", // ← ココ
    "fideloper/proxy": "^4.0",
    "laravel/framework": "5.7.*",
    "laravel/tinker": "^1.0"
},

導入されている事を確認できました。

カラム変更用マイグレーションファイルの生成

パッケージの導入が完了したら、マイグレーションファイルの生成を行っていきます。

前回のマイグレーション生成時には、本を管理する「books 」テーブルを作成しましたので、今回はここに、「販売数(何冊売れたか)」のカラムを追加してみようと思います。テーブル生成時のコマンドとは微妙に違うので注意してください。

Laravel ルートディレクトリへ移動して、以下の artisan コマンドを叩きます。

# Laravel のルートディレクトリへ移動
cd /path/to/laravel

# マイグレーション生成
php artisan make:migration add_column_sales_books_table --table=books

前回同様、
php artisan make:migration [マイグレーションファイル名] --table=[テーブル名]
としてコマンドを組み立ててください。

この時に注意したいのが、前回も言った通りマイグレーションファイル名はそのままクラス名になりますので、分かりやすい名前をつけましょう。

今回の場合は「add_column_sales_books_table 」なので、クラス名は
AddColumnSalesBooksTable
というクラス名で生成されます。

また、オプションもテーブル生成時のものと異なっています。「--create=」が「--table=」になっている事に気が付いたでしょうか?

Schema ファサードによって実行されるメソッドを「table 」にて生成するという意味ですが、まあ細かい事は抜きにして、お約束としてつけましょう。

以下は実行結果です。マイグレーションファイルが生成されました。

# 実行結果
[demo@localhost laravel]$ php artisan make:migration add_column_sales_books_table --table=books
Created Migration: 2018_11_24_183257_add_column_sales_books_table

前回同様、laravel/database/migrations 配下に生成されています。

laravel
├─ database
│   ├─ migrations
│   │   ├─ 2014_10_12_000000_create_users_table.php
│   │   ├─ 2014_10_12_100000_create_password_resets_table.php
│   │   ├─ 2018_11_24_172221_create_books_table.php
│   │   └─ 2018_11_24_183257_add_column_sales_books_table.php // ← ココ

マイグレーションファイルの確認とスキーマビルダ記述

それでは、生成したマイグレーションファイルを開いてスキーマビルダにて追加カラムを記述していきますが、まずはファイルを確認します。

<?php

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

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

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

テーブル生成の時と一見変わりないように見えますが、Schema クラスのメソッドが create から table に変更されています。

ではここにカラム追加の記述を行っていきますが、up メソッドにはカラム追加の記述を、down メソッドにはロールバック時の処理(無かった事にする処理)をスキーマビルダで記述します。
こんな感じになりました。

<?php

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

class AddColumnSalesBooksTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::table('books', function (Blueprint $table) {
          $table->integer('sales')->default(0)->index('index_sales')->after('price')->comment('販売数');
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::table('books', function (Blueprint $table) {
          $table->dropColumn('sales');
        });
    }
}

まず、up() メソッドですが

$table->integer('sales')->default(0)->index('index_sales')->after('price')->comment('販売数');

INT 型のカラム「sales 」を、デフォルト値「0 」として、インデックスを張り、price カラムの次に、コメント「販売数」として追加

続いて down() メソッドは

$table->dropColumn('sales');

カラム「sales 」を削除(drop)する
という意味になっています。
尚、今回はカラム追加を行いましたが、カラムの変更・削除等もここに何を記述するかで行えますので、各自必要な処理を記述してください。

マイグレーションを実行してカラムを追加する

それではマイグレーションを実行してみましょう。
Laravel のルートディレクトリへ移動し、以下の artisan コマンドを叩きます。

# Laravel のルートディレクトリへ移動
cd /path/to/laravel

# マイグレーション実行
php artisan migrate

# 実行結果
[demo@localhost laravel]$ php artisan migrate
Migrating: 2018_11_24_183257_add_column_sales_books_table
Migrated:  2018_11_24_183257_add_column_sales_books_table

実行が完了したら、実際にカラムが追加されているかを確認してみましょう。

# マイグレーション実行前
mysql> show columns from books;
+------------+------------------+------+-----+-------------------+-----------------------------+
| Field      | Type             | Null | Key | Default           | Extra                       |
+------------+------------------+------+-----+-------------------+-----------------------------+
| id         | int(10) unsigned | NO   | PRI | NULL              | auto_increment              |
| book_name  | varchar(255)     | NO   |     | NULL              |                             |
| author     | varchar(100)     | NO   | MUL | NULL              |                             |
| price      | int(11)          | NO   |     | NULL              |                             |
| stocks     | int(11)          | NO   | MUL | NULL              |                             |
| release_dt | timestamp        | NO   |     | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP |
| created_at | timestamp        | YES  |     | NULL              |                             |
| updated_at | timestamp        | YES  |     | NULL              |                             |
+------------+------------------+------+-----+-------------------+-----------------------------+

# 

# マイグレーション実行後
mysql> show columns from books;
+------------+------------------+------+-----+-------------------+-----------------------------+
| Field      | Type             | Null | Key | Default           | Extra                       |
+------------+------------------+------+-----+-------------------+-----------------------------+
| id         | int(10) unsigned | NO   | PRI | NULL              | auto_increment              |
| book_name  | varchar(255)     | NO   |     | NULL              |                             |
| author     | varchar(100)     | NO   | MUL | NULL              |                             |
| price      | int(11)          | NO   |     | NULL              |                             |
| sales      | int(11)          | NO   | MUL | 0                 |                             |
| stocks     | int(11)          | NO   | MUL | NULL              |                             |
| release_dt | timestamp        | NO   |     | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP |
| created_at | timestamp        | YES  |     | NULL              |                             |
| updated_at | timestamp        | YES  |     | NULL              |                             |
+------------+------------------+------+-----+-------------------+-----------------------------+

カラムが意図した通りに追加されている事が確認できました。

ロールバックを行う

行ったマイグレーションをロールバック(無かった事にする)も出来ます。 その場合には、down() メソッドが実行されます。 今回の場合には、sales カラムが削除(drop)されるという事になります。

ロールバックには「step 」というオプションがあり、どれだけのマイグレーションを元に戻したいかを設定できます。オプションを付けなければ、単純に、最後に行ったマイグレーション実行がロールバックされます。
試しに、今行ったマイグレーションをロールバックしてみます。

# Laravel のルートディレクトリへ移動
cd /path/to/laravel

# 最後のマイグレーションをロールバックする
php artisan migrate:rollback

# 実行結果
[demo@localhost laravel]$ php artisan migrate:rollback
Rolling back: 2018_11_24_183257_add_column_sales_books_table
Rolled back:  2018_11_24_183257_add_column_sales_books_table

ロールバックが実行されました。
データベースを確認してみます。

# ロールバック実行後
mysql> show columns from books;
+------------+------------------+------+-----+-------------------+-----------------------------+
| Field      | Type             | Null | Key | Default           | Extra                       |
+------------+------------------+------+-----+-------------------+-----------------------------+
| id         | int(10) unsigned | NO   | PRI | NULL              | auto_increment              |
| book_name  | varchar(255)     | NO   |     | NULL              |                             |
| author     | varchar(100)     | NO   | MUL | NULL              |                             |
| price      | int(11)          | NO   |     | NULL              |                             |
| stocks     | int(11)          | NO   | MUL | NULL              |                             |
| release_dt | timestamp        | NO   |     | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP |
| created_at | timestamp        | YES  |     | NULL              |                             |
| updated_at | timestamp        | YES  |     | NULL              |                             |
+------------+------------------+------+-----+-------------------+-----------------------------+

ロールバックが実行され、最後に行ったマイグレーションである sales カラムの追加が無かった事(追加する前に戻る)になりました。

まとめ

今回はマイグレーションにてカラムの変更を行いました。
次回はシーティングという機能を使い、マイグレーション時に初期データを投入する手順を解説します。

next: Laravel の Seeding(シーディング)機能を使い、データベースへ初期(テスト)データを投入する

Author

rito

  • Backend Engineer
  • Tokyo, Japan
  • PHP 5 技術者認定上級試験 認定者
  • 統計検定 3 級