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

今回は Laravel の migration(マイグレーション)で、作成したテーブルに対して、カラムの追加、変更、削除などを行います。
Contents
- 開発環境
- マイグレーションでデータベースを管理し開発を行う
- カラム変更マイグレーションの準備
- カラム変更用マイグレーションファイルの生成
- マイグレーションファイルの確認とスキーマビルダ記述
- マイグレーションを実行してカラムを追加する
- ロールバックを行う
開発環境
前回は同機能でテーブルの作成までを行いました。マイグレーションについての基本や再現環境等含め、前回の続きとして進めていきますので、必要な場合はそちらを確認してください。
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 カラムの追加が無かった事(追加する前に戻る)になりました。
まとめ
今回はマイグレーションにてカラムの変更を行いました。
次回はシーティングという機能を使い、マイグレーション時に初期データを投入する手順を解説します。