エンジニアチャレンジ

27歳営業マンからWebエンジニアを目指すブログです

【Laravel】 Specified key was too long; max key length is 767 bytes

◾️エラー概要

Laravel5.5でmigrationを実行したところ、以下のエラー発生。

 [Illuminate\Database\QueryException]
  SQLSTATE[42000]: Syntax error or access violation: 1071 
Specified key was too long; max key length is 767 bytes 
(SQL: alter table `users` add unique `users_email_unique`(`email`))

[Doctrine\DBAL\Driver\PDOException]
  SQLSTATE[42000]: Syntax error or access violation: 1071 
Specified key was too long; max key length is 767 bytes

  [PDOException]
  SQLSTATE[42000]: Syntax error or access violation: 1071 
Specified key was too long; max key length is 767 bytes

 

 

◾️原因

Laravel5.4から、標準charasetがutf8mb4に変わった。

標準charasetがutf8mb4となったことで1文字あたりの最大byte数が4bytesに増えた。

MySQLではユニーク制約を付けたカラムには767bytesまでしか入らない。

MySQLではPRIMARY_KEYおよびUNIQUE_KEYを付けたカラムには、

768bytes以上のカラムに対するインデックスキーは設定できません!

※5.7.7以降のバージョンだと解消されているみたい。

 

Laravelの場合、データベースのcharasetは「config/database.php」で定義されているので確認してみましょう。

Laravel5.3までは、以下のようにUTF-8

'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',

UTF-8は1文字が3bytesのため、

varchar(255)は255文字 × 3bytes=765bytes。

問題なくインデックスを設定することができていました。 

Laravel5.4からは、utf8mb4が標準になりました。

'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',

utf8mb4は1文字4bytesとしてあつかわれるため、

制限の767バイトを超えてしまい、MySQLのエラーが出力されるようになりました。

 

 

 

◾️解決策

app\Providers\AppServiceProvider.php】の、boot()を下のように書き換えて上書き。

一度MySQLを落として、再度migrateしたら無事解決されました。

 

php|AppServiceProvider.php
use Illuminate\Support\Facades\Schema;

public function boot()
{
    Schema::defaultStringLength(191);
}