1. beer_geek

    No comment

    beer_geek
Changes in title
-Laravel5.4 + MySQL5.5.9 でusersテーブルのマイグレーション時に Syntax error
+Laravel5.4~ + ~MySQL5.7.7 でusersテーブルのマイグレーションを実行すると Syntax error が発生する
Changes in body
Source | HTML | Preview
@@ -1,81 +1,89 @@
## はじめに
-初投稿&Gistの自分用メモ書きを公開しただけなので読みにくかったら申し訳ない
+
+古い備忘録だが、いまだに定期的にアクセスがあるので全面的に加筆修正した。
+PHPは7系に追従していても、MySQLのバージョンはいまだ5.5~5.6、という環境も多いのだろう
### 前提
-+ Laravel5.4
-+ MySQL5.5.9
-+ `artisan make:auth`で作成されるusersテーブルで発生
++ Laravel5.4以上
++ MySQL5.7.7未満
## 現象
-Laravel5.4を新規導入し、意気揚々とmigrationを叩いたら、
-以下のようなエラー(例外)が出た。
+上記環境のもとで、`$ php artisan make:auth`で自動作成されるマイグレーションファイルに対し、
+`$ php artisan migrate` を実行すると、以下のエラーが発生する。
> [Illuminate\Database\QueryException]
SQLSTATE[42000]: Syntax error or access violation: 1071 Specified key was t
oo long; max key length is 767 bytes (SQL: alter table `users` add unique `
users_email_unique`(`email`))
> [PDOException]
SQLSTATE[42000]: Syntax error or access violation: 1071 Specified key was t
oo long; max key length is 767 bytes
## 原因
### 1. Laravel5.4から標準charasetがutf8mb4に変わった
標準charasetがutf8mb4となったことで1文字あたりの最大byte数が4bytesに増えた。
-### 2. MySQLではユニーク制約を付けたカラムには767bytesまでしか入らない
-MySQLではPRIMARY_KEYおよびUNIQUE_KEYを付けたカラムには最大767bytesまでしか入らないらしい。
-ver5.7.7以降だと解消されている模様
+### 2. MySQL5.7.7未満ではユニーク制約を付けたカラムは最大767bytes
+マイグレーションファイルにvarcharカラムの大きさを指定しなかった場合、`varchar(255)` のカラムが作成される。
+
+```php
+ $table->string('email')->unique();
+```
+
+一方、MySQL5.7.7以前のバージョンでは、PRIMARY_KEYおよびUNIQUE_KEYを付けたカラムには最大767bytesまでしか入らない
+4bytes,255文字では767bytesを超えてしまう。これがエラーの原因
## 対策
対策としては以下の3つが考えられる。
1. MySQLのバージョンを最新にする
2. 使用するcharasetをutf8mb4から変更する
-3. カラムの最大を変更し、767bytes以上の文字列が入らないようにする
+3. カラムの最大を変更し、767bytes以上の文字列が入らないようにする
-今回は3を選択。
-## 変更点
+### 対策1:MySQLのバージョンを最新にする
-### 前提
-Laravelではマイグレーション時にカラムの大きさを指定しなかった場合、
-255文字まで入るように設定されている。
-下記のマイグレーションを実行するとemail varchar(255)のテーブルが作成される。
+特段の事情がなければベストの対応。[MySQL5.6系のPremier Support期限は2018年2月に終了している。](https://qiita.com/shogomuranushi/items/10df42a3c7037d588efc)
+
+### 対策2:使用するcharasetをutf8mb4から変更する
+
+Laravel5.3まではcharsetの標準設定はUTF-8だった。
+`config/database.php` よりcharsetを以下のように変更すれば、Laravel5.3以前と同じ挙動で使用することができる。
+ただし、絵文字 :sushi: は使えなくなる。
```php
- $table->string('email')->unique();
+'charset' => 'utf8',
+'collation' => 'utf8_unicode_ci',
+```
+
+### 対策3:カラムの最大長を変更し、767bytes以上の文字列が入らないようにする
+
+`varchar(191)` のカラムを作成すれば、191 * 4 = 764bytesのため、エラーが発生しない。
+
+```php
+//個別で指定する例
+ $table->string('email', 191)->unique();
```
-このときのカラムの大きさを変更する。
-すなわち、上記マイグレーション実行時にemail varchar(191)となるテーブルが作成されれば、
-utf8mb4を使用していても767bytes以上の文字列が入ることはない。
-
-### 実装
-app\Providers\AppServiceProvider.php
-に以下を追加する。
+上記のようにカラムごと個別に最大長を指定してもよいが、
+`app\Providers\AppServiceProvider.php` に以下の記載を追加することで、最大長未指定時のdefault値を変更することが可能である
```php
use Illuminate\Support\Facades\Schema;
public function boot()
{
Schema::defaultStringLength(191);
}
```
-これでemail varchar(191)となるテーブルが作成され、エラーが発生しなくなった。
-
-データベースの定義が大きく変わるので、
-すでに稼働中のシステムであればcharasetを変更したほうがいいと思う
+これでマイグレーションを実行すれば、正常に動作する
## 参考URL
1. https://laravel-news.com/laravel-5-4-key-too-long-error
2. http://d.hatena.ne.jp/tanamon/20090930/1254332746
-
-1見れば正直この記事いらない気もする。
-日本語記事的な需要があるのであれば、これからもたまに投稿したい。