はじめに
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');
関連