1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

LaravelのマイグレーションでIndexが長いとエラーになる時の対処法

Posted at

はじめに

Laravelでマイグレーションをいつものように実行していると、

Syntax error or access violation: 1059 Identifier name ...以下略

という問題が発生したことがありました。
どういった理由で発生するのかを調べたので記事としてまとめたいと思います。

動作確認環境

  • PHP 8.0
  • Laravel 8.0
  • MySQL 8.0

※下位環境でも動作する場合がございます

Laravelのマイグレーション

/**
 * Run the migrations.
 *
 * @return void
 */
public function up()
{
    Schema::create('dummy_users', function (Blueprint $table) {
        $table->id();
        $table->string('name')->comment('name');
        $table->string('session_token')->comment('session_token');
        $table->string('user_token')->comment('user_token');
        $table->string('sub_name')->comment('sub_name');
        $table->integer('ios_gold')->unsigned()->comment('ios_gold');
        $table->integer('android_gold')->unsigned()->comment('android_gold');
        $table->timestamp('last_login_datetime')->nullable()->comment('last_login_datetime');
        $table->integer('updated_at_timestamp')->unsigned()->comment('updated_at_timestamp');
        $table->integer('updated_at_timestamp2')->unsigned()->comment('updated_at_timestamp2');
        $table->timestamp('created_at')->nullable()->comment('created_at');
        $table->timestamp('updated_at')->nullable()->comment('updated_at')->index();

        $table->index(['android_gold', 'session_token', 'user_token', 'name']);
    });
}

Laravelでは上記のように

$table->index(['android_gold', 'session_token', 'user_token', 'name']);

と書くことでIndexキーを貼ることができますが、このIndexが一定文字数以上になるとエラーが発生してしまいます。

文字数上限

MySQLは、Indexキーの文字数が65文字以上になるとエラーが発生します。

LaravelのIndexキーの仕組み

$table->index(['android_gold', 'session_token', 'user_token', 'name']);

Laravelは上記のように記述すると、

dummy_ussers_android_gold_session_token_user_token_name_index

というキー名が自動的に付けられます。

/**
 * Create a default index name for the table.
 *
 * @param  string  $type
 * @param  array  $columns
 * @return string
 */
protected function createIndexName($type, array $columns)
{
    $index = strtolower($this->prefix.$this->table.'_'.implode('_', $columns).'_'.$type);

    return str_replace(['-', '.'], '_', $index);
}

LaravelのIlluminate\Database\Schema\Blueprintの上記メソッドで定義されている通り、
テーブル名などが自動的にキー名に付くようになります。
その影響でテーブル名が長かったりすると、Indexとして使える文字数が少なくなり、エラーになる可能性も高くなります。

対処法

Laravelの自動名付けを使うと↑のロジックが使われ、結果的に長めのキー名になってしまいます。
これを避けるためには、第2引数を付けることで任意のIndex名を付けることができます。

$table->index(['android_gold', 'session_token', 'user_token', 'name'], 'aiueo');

関連

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?