Laravel7系でmigrateコマンドを使って不要なテーブルをDROPする


# 概要

アプリケーションの改修を進めるなかで、不要になったテーブル（RDB）を DROP する必要性が発生した。

「たしか Laravel でマイグレーションする機能（コマンド）があったよな？」と思いだしたので、実行手順を整理する。

# 前提条件

今回動作を確認した環境は以下のとおりです。

- PHP 7.4.0
- Laravel 7.12.0
- MySQL 8.0.35

# 詳細

## Laravel のマイグレーション機能

Laravel は PHP で Web アプリケーション開発を行う際によく利用される MVC フレームワーク。

Laravel には`artisan`というコマンドが用意されており、Model や Controller、Seed の作成といった便利な機能がある。

そのなかで、マイグレーション機能というものがあり、DB テーブルの作成/削除やカラム追加/削除/変更など、開発をしている中で DB に対して行いたい操作がだいたい網羅されてる。

（[【公式】Laravel 11.x - Migrations](https://laravel.com/docs/11.x/migrations)）

## 実際のコマンド実施手順

実際に、今回やりたいこと「不要なテーブルを DROP する」をマイグレーション機能を使って実装してみる。

### おおまかな流れ

作業の流れとしては、以下の感じ。

1. マイグレーションファイルの作成
2. ロジック実装
3. migrate コマンドで DB に反映

### 事前確認

`artisan`コマンドが実行可能であることを確認する。

Laravel プロジェクトのルートで以下コマンドを実施。

```
php artisan
```

実行結果が下記のように実行できるコマンドのリストが出力されていれば、`artisan`コマンドが実行できているので準備 OK。

```
Laravel Framework 7.12.0

Usage:
  command [options] [arguments]

Options:
  -h, --help            Display this help message
  -q, --quiet           Do not output any message
  -V, --version         Display this application version
      --ansi            Force ANSI output
      --no-ansi         Disable ANSI output
  -n, --no-interaction  Do not ask any interactive question
      --env[=ENV]       The environment the command should run under
  -v|vv|vvv, --verbose  Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug

Available commands:
  clear-compiled           Remove the compiled class file
  down                     Put the application into maintenance mode
  env                      Display the current framework environment
  help                     Displays help for a command
  inspire                  Display an inspiring quote
  list                     Lists commands
  migrate                  Run the database migrations
  optimize                 Cache the framework bootstrap files
  serve                    Serve the application on the PHP development server
  test                     Run the application tests
  tinker                   Interact with your application
  ui                       Swap the front-end scaffolding for the application
  up                       Bring the application out of maintenance mode
 auth
  auth:clear-resets        Flush expired password reset tokens
 cache
  cache:clear              Flush the application cache
  cache:forget             Remove an item from the cache
  cache:table              Create a migration for the cache database table
 command
  command:sendmail         Command description
  command:userActiveCheck  非アクティブユーザーに通知を行い、停止フラグをONにする
 config
  config:cache             Create a cache file for faster configuration loading
  config:clear             Remove the configuration cache file
 db
  db:seed                  Seed the database with records
  db:wipe                  Drop all tables, views, and types
 event
  event:cache              Discover and cache the application's events and listeners
  event:clear              Clear all cached events and listeners
  event:generate           Generate the missing events and listeners based on registration
  event:list               List the application's events and listeners
 key
  key:generate             Set the application key
 make
  make:cast                Create a new custom Eloquent cast class
  make:channel             Create a new channel class
  make:command             Create a new Artisan command
  make:component           Create a new view component class
  make:controller          Create a new controller class
  make:event               Create a new event class
  make:exception           Create a new custom exception class
  make:factory             Create a new model factory
  make:job                 Create a new job class
  make:listener            Create a new event listener class
  make:mail                Create a new email class
  make:middleware          Create a new middleware class
  make:migration           Create a new migration file
  make:model               Create a new Eloquent model class
  make:notification        Create a new notification class
  make:observer            Create a new observer class
  make:policy              Create a new policy class
  make:provider            Create a new service provider class
  make:request             Create a new form request class
  make:resource            Create a new resource
  make:rule                Create a new validation rule
  make:seeder              Create a new seeder class
  make:test                Create a new test class
 migrate
  migrate:fresh            Drop all tables and re-run all migrations
  migrate:install          Create the migration repository
  migrate:refresh          Reset and re-run all migrations
  migrate:reset            Rollback all database migrations
  migrate:rollback         Rollback the last database migration
  migrate:status           Show the status of each migration
 notifications
  notifications:table      Create a migration for the notifications table
 optimize
  optimize:clear           Remove the cached bootstrap files
 package
  package:discover         Rebuild the cached package manifest
 queue
  queue:failed             List all of the failed queue jobs
  queue:failed-table       Create a migration for the failed queue jobs database table
  queue:flush              Flush all of the failed queue jobs
  queue:forget             Delete a failed queue job
  queue:listen             Listen to a given queue
  queue:restart            Restart queue worker daemons after their current job
  queue:retry              Retry a failed queue job
  queue:table              Create a migration for the queue jobs database table
  queue:work               Start processing jobs on the queue as a daemon
 route
  route:cache              Create a route cache file for faster route registration
  route:clear              Remove the route cache file
  route:list               List all registered routes
 schedule
  schedule:run             Run the scheduled commands
 session
  session:table            Create a migration for the session database table
 storage
  storage:link             Create the symbolic links configured for the application
 stub
  stub:publish             Publish all stubs that are available for customization
 ui
  ui:auth                  Scaffold basic login and registration views and routes
  ui:controllers           Scaffold the authentication controllers
 vendor
  vendor:publish           Publish any publishable assets from vendor packages
 view
  view:cache               Compile all of the application's Blade templates
  view:clear               Clear all compiled view files
 webpush
  webpush:vapid            Generate VAPID keys.
```

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

まずは`make`コマンドでマイグレーションファイルのガワを作成する。

```
php artisan make:migration {任意のファイル名}
```

たとえば ↓ とか

```
php artisan make:migration drop_xxxxx_table
```

これで、プロジェクト内の`database/migrations/`に、指定したファイル名で新しいマイグレーションファイルが作成される。

この時 DB の`migrations`テーブル（Laravel で自動生成されるテーブル）にもファイル名と同じレコードが作成される。

次に、以下コマンドでマイグレーションファイルのリストを出力し状態を確認

```
php artisan migrate:status
```

結果

```
+------+---------------------------------------------------+-------+
| Ran? | Migration                                         | Batch |
+------+---------------------------------------------------+-------+
| No   | yyyy_mm_dd_hhMMss_drop_xxxxx_table                | 1     |
+------+---------------------------------------------------+-------+
```

`Ran?`のところを見ると、このマイグレーションが未実施であることがわかる。

`Batch`のほうは、実行順（数字が小さいものから順に実行されたことを示す）をあらわす。

### ロジック実装

作成したマイグレーションファイルに具体的なロジックを実装する。

まず、作成直後のマイグレーションファイルはこんな感じ

```php
<?php

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

class Test extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        //
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        //
    }
}
```

`up()`にはマイグレーション実行時に実施してほしい処理を、`down()`にはマイグレーションをロールバック（取り消し）した際に実施してほしい処理を書く。

まずは`up()`から。

```php
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::dropIfExists('test');
    }
```

`dropIfExists()`は、指定したテーブルが存在したら DROP 操作を実行する関数。

今回やりたいことは、「不要になったテーブルを DROP したい」なので、`up()`に書くのはコレだけで OK。

次に考えるのはロールバック時の処理ですが、「XXX テーブルを DROP する」の反対を考えればよいので、「XXX テーブルを作成する」処理を実装すればよさそう。

```php
    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::create('test', function (Blueprint $table) {
            $table->increments('id');
            $table->integer('user_id')->unsigned();
            $table->timestamps();

            $table->foreign('user_id')->references('id')->on('users');
        });
    }
```

例として、`users`テーブルを外部キー参照している`test`テーブルの CREATE 処理を実装した。

「DROP した XXX テーブルを元に戻すには、データの復旧も必要では？」という疑問はあるけど、仮に DROP しちゃってからやっぱり復元したいとなったら、別の手段（バックアップからリストアとか）も必要になってくると思うので、マイグレーションとしての実装はこれでよしとする。

### migrate コマンドで DB に反映

最後に、`migrate`コマンドで DB にマイグレーション内容を反映。

```
php artisan migrate
```

このコマンドを実行することで、`migrate:status`で`Ran?`が No のマイグレーションだけが実行され、DB に結果が反映される。

実行後に改めてステータスを確認。

```
php artisan migrate:status
```

結果

```
+------+---------------------------------------------------+-------+
| Ran? | Migration                                         | Batch |
+------+---------------------------------------------------+-------+
| Yes  | yyyy_mm_dd_hhMMss_drop_xxxxx_table                | 1     |
+------+---------------------------------------------------+-------+
```

これで DB から`test`テーブルが DROP された！

# まとめ

Laravel のマイグレーション機能めっちゃ便利！

DB への変更履歴をコード管理できるのも、長期的に機能追加等の開発をしていくうえでは心強いですよね。

今更ですが、Laravel って 11 系までリリースされてるんですね...キャッチアップせねば。

他にも Laravel の`artisan`コマンドでできることはたくさんあるので、公式ドキュメントを参照してみてください。

# 参考

- [Laravel 公式 Database: Migrations](https://laravel.com/docs/11.x/migrations)