Laravel で外部キー制約の onDelete / onUpdate をマイグレーション後に設定する + 論理削除でハマったこと

# やりたいこと
- `Company` と `Employee`のように親子関係にあるテーブルを作成
- `employee`テーブルに`company_id`という外部キーを設定
- その後、 `onDelete` `onUpdate`に対する挙動を設定し忘れたことに気づいたので後から設定をしたい

# マイグレーションファイル
- companies

```timestamp_create_companies_table.php
class CreateCompanyTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('companies', function (Blueprint $table) {
            $table->increments('id');
            $table->string('name');
            $table->timestamps();
            $table->softDeletes();
        });
    }

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

- employee

```timestamp_create_employee_table.php
class CreateEmployeeTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('employee', function (Blueprint $table) {
            $table->increments('id');
            $table->string('name')->nullable();
            $table->integer('company_id')->unsigned();
            $table->foreign('company_id')->references('id')->on('companies');
            $table->timestamps();
            $table->softDeletes();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('employee');
    }
}
```
マイグレーションは問題なくて、その後も色々なテーブルを追加していった後、onDelete / onUpdate の設定ができていないことに気づいて、「全部ロールバックするのも気が重いし、一部分だけ弄れないかな…」と逡巡して以下の方法を取った。

# やったこと
あまりお行儀がよくないかもしれないが、 `employee`テーブルの`company_id`だけを drop するマイグレーションファイルを作り、`php artisan migrate`を実行。
その後外部キー制約を再設定するマイグレーションファイルを作って、同様に`php artisan migrate`。


- 外部キーを一旦Drop

```timestamp_drop_foreign_key_from_employee.php
class DropForeignKeyFromEmployee extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        //外部キー制約を引き剥がす時は dropForeign('テーブル名'_'外部キー名'_foreign);
        Schema::table('employee', function (Blueprint $table) {
            $table->dropForeign('employee_company_id_foreign');
        });
    }
}
```

```timestamp_reset_foreign_key_to_employee.php
public function up()
    {
        //子テーブルに対象レコードがある場合、親テーブルのレコード削除を禁止 ->onDelete('restrict');
        //親テーブルのレコード更新は許可 ->onUpdate('cascade');
        Schema::table('employee', function (Blueprint $table) {
            $table->index('company_id');
            $table->foreign('company_id')->references('id')->on('companies')
                ->onDelete('restrict')
                ->onUpdate('cascade');
        });
    }

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

```

# 問題点
このやり方だとロールバックした時に`DropForeignKeyFromEmployee `エラーで怒られる。なので、最初からなるべくテーブル作成時に onDelete / onUpdate の条件は慎重に考えて設定した方がいい。うまく後付けで設定できる方法があればコメントで教えていただきたいです。個人的に思いつくのがMySQLのコマンドで直接テーブルを書き換える手段だけなので…

# その他ハマったこと
`onDelete('restrict')`を設定したあと、Laravel アプリケーションから`Company::destroy`で実際に削除を試してみたところ、なんと制約に引っかからず普通に削除できてしまった…
どうやら`use SoftDelete`で論理削除をさせている場合、物理削除と違って`deleted_at`にタイムスタンプを書き込むだけなので制約をすり抜けてしまうらしい…。早めに知っておきたかった。

参考リンク
[What if onDelete is restrict instead of cascade?](https://github.com/michaeldyrynda/laravel-cascade-soft-deletes/issues/3)

[マイグレーションまとめ(Laravel5)]
(https://qiita.com/hththt/items/ae871f59b337f209d1ad)