RitoLabo

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

  • 公開:
  • 更新:
  • カテゴリ: PHP Laravel
  • タグ: PHP,Laravel,migration,SchemaBuilder,5.5,5.4,5.3,5.6,5.7

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

アジェンダ
  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(シーディング)機能を使い、データベースへ初期(テスト)データを投入する