Laravel移行エラー:構文エラーまたはアクセス違反:1071指定されたキーが長すぎます。キーの最大長は767バイトです


177

Laravel 5.4での移行エラー php artisan make:auth

[Illuminate \ Database \ QueryException] SQLSTATE [42000]:構文エラーまたはアクセス違反:1071指定されたキーが長すぎます。キーの最大長は767バイトです(SQL:alter tabl e usersadd unique users_email_uniqueemail))

[PDOException] SQLSTATE [42000]:構文エラーまたはアクセス違反:1071指定されたキーが長すぎます。キーの最大長は767バイトです


3
あなたは答えであなたの質問に答えるべきです。問題ではありません。stackoverflow.com/help/self-answer
Can Vural

@ can-vuralの提案に感謝しました。
absiddiqueLive

回答:


283

公式ドキュメントによると、これは非常に簡単に解決できます。

次の2行のコードをAppServiceProvider.php(/app/Providers/AppServiceProvider.php)に追加します。

use Illuminate\Database\Schema\Builder; // Import Builder where defaultStringLength method is defined

function boot()
{
    Builder::defaultStringLength(191); // Update defaultStringLength
}

MySQLは常に4バイトのUTF8フィールドの最大量を予約しているため、DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ciで255 + 255を使用します。キーの長さの上限である767を超えています。@scaisedgeによって


3
この解決策に注意してください。たとえば、メールフィールドにインデックスを付ける場合、保存されるメールの最大長は191文字です。これは公式のRFCの状態よりも少ないです。
shock_gone_wild 2017


これは機能しており、有効な解決策ですが、このアプローチを使用すると潜在的な落とし穴があることを指摘したいと思います。
shock_gone_wild 2017

この解決策が将来お尻を噛まないように願っていますが、今のところこれでうまくいきます。ただし、メールのインデックス登録には注意が必要です。
deusofnull

4
なぜ191文字@absiddiqueLive
PseudoAj

121

上記の解決策と追加されている公式の解決策がなぜなのかわかりません

Schema::defaultStringLength(191);

AppServiceProvider私のために動作しませんでした。うまくいったのはdatabase.phpconfigフォルダ内のファイルを編集することでした。編集するだけ

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

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

そして、絵文字のような拡張マルチバイト文字を保存することはできませんが、それはうまくいくはずです

Laravel 5.7でそれを行いました。それが役に立てば幸い。


5
この文字セットを使用すると、標準ASCIIのみを保存でき、アラビア語、ヘブライ語、ほとんどのヨーロッパのスクリプト、そしてもちろん絵文字などのマルチバイトの特殊文字は保存できません。stackoverflow.com/a/15128103/4233593
Jeff Puckett 2017

7
use Illuminate\Support\Facades\Schema;上部のこの部分を逃したと思います。
圧迫

@KoushikDasどのバージョンのLaravelを使用していますか?
圧迫

今私は6.0にいます。最初は多分5.7か5.6でやったと思います。
Koushik Das

2
utf8mb4照合は理由があり、私はあなたができる場合は、それを使用することをお勧めします。
火曜日

85

それは私のためのquickestソリューションなので、私はここでこの答えを追加しています。デフォルトのデータベースエンジンを'InnoDB'オンに 設定するだけです

/config/database.php

'mysql' => [
    ...,
    ...,
    'engine' => 'InnoDB',
 ]

次にphp artisan config:cache、構成キャッシュをクリアして更新するために実行します


1
これは、この質問に対する公式の回答/解決策になるはずです...ありがとう
Syamsoul Azrien

1
これは他の人には回避策あり、実際のソリューションです
ルイス・クーニャ

3
しかし、これの背後にある論理は何ですか
Zulfiqar Tariq

1
それが正しい解決策です。しかし、なぜそれがデフォルトのインストールに含まれていないのですか?
Ankit Chauhan

38

では、AppServiceProvider.phpこのコードをファイルの先頭に含めます。

use Illuminate\Support\Facades\Schema;

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

助けてくれてありがとう
デッドマン

24

この問題は、データベースのバージョンによってLaravel 5.4で発生します。

(セクションの)ドキュメントによるとIndex Lengths & MySQL / MariaDB

Laravelはutf8mb4デフォルトで文字セットを使用します。これには、データベースに「絵文字」を格納するためのサポートが含まれます。5.7.7リリースより前のバージョンのMySQLまたは10.2.2リリースより前のMariaDBを実行している場合、MySQLがインデックスを作成するために、移行によって生成されるデフォルトの文字列長を手動で構成する必要がある場合があります。これを設定するには、Schema::defaultStringLength内でメソッドを呼び出し ますAppServiceProvider

言い換えれば、中<ROOT>/app/Providers/AppServiceProvider.php

// Import Schema
use Illuminate\Support\Facades\Schema;
// ...

class AppServiceProvider extends ServiceProvider
{

public function boot()
{
    // Add the following line
    Schema::defaultStringLength(191);
}

// ...

}

しかし、他の答えのコメントが言うように:

この解決策に注意してください。たとえば、メールフィールドにインデックスを付ける場合、保存されるメールの最大長は191文字です。これは公式のRFCの状態よりも少ないです。

したがって、ドキュメントは別のソリューションも提案しています:

または、innodb_large_prefixデータベースのオプションを有効にすることもできます。このオプションを適切に有効にする方法については、データベースのドキュメントを参照してください。


16

変更したくない人のためにAppServiceProvider.php。(私の意見では、AppServiceProvider.php移行のためだけに変更することは悪い考えです)

database/migrations/以下のように、データ長を移行ファイルに追加できます。

create_users_table.php

$table->string('name',64);
$table->string('email',128)->unique();

create_password_resets_table.php

$table->string('email',128)->index();

電子メールは最大255(ish)文字になる可能性があるため、これは問題になる可能性があります
ハーフクレイズ

あなたは正しい@HalfCrazedですが、私はこの回答をお勧めしますstackoverflow.com/questions/1297272
helloroy

私の問題はこの解決策で正確に解決できました。私のフィールドはメールではありませんでした。
タラカデヴィンダ

11

コマンドの使用中にlaravelで作業中にこのエラーが発生した場合:php artisan migrate ファイルに2行追加するだけです:app-> Providers-> AppServiceProvider.php

  1. use Schema;
  2. Schema::defaultStringLength(191);

この画像を確認しください。その後、php artisan migrateコマンドを再度実行してください。


1
「スキーマの使用」を追加することは非常に重要です。これが最良の答えです
hxwtch

このように2行目の前にバックスラッシュ '\'を追加することで、これを1行で行うこともできます\Schema::defaultStringLength(191);
Tahir Afridi

10

私に役立つ 2つの溶液を追加します。

最初の解は

  1. database.phpファイルをinsde config dir / folderで開きます。
  2. 編集'engine' => null,する'engine' => 'InnoDB',

    これでうまくいきました。

2番目の溶質は:

  1. database.phpファイルをinsde config dir / folderで開きます。
    2. 編集
    'charset' => 'utf8mb4', 'collation' => 'utf8mb4_unicode_ci',
    します

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


幸運を


10

app / Providers / AppServiceProvider.phpのこれらの行を更新して挿入します

use Illuminate\Support\Facades\Schema;  // add this line at top of file

public function boot()
{
    Schema::defaultStringLength(191); // add this line in boot method
}

8

私はこの問題を解決し、私のデータベース( 'charset' => 'utf8')( 'collat​​ion' => 'utf8_general_ci')のようにconfig- > database.phpファイルを編集したので、私の問題は次のようにコードを解決しました従う:

'mysql' => [
        'driver' => 'mysql',
        'host' => env('DB_HOST', '127.0.0.1'),
        'port' => env('DB_PORT', '3306'),
        'database' => env('DB_DATABASE', 'forge'),
        'username' => env('DB_USERNAME', 'forge'),
        'password' => env('DB_PASSWORD', ''),
        'unix_socket' => env('DB_SOCKET', ''),
        'charset' => 'utf8',
        'collation' => 'utf8_general_ci',
        'prefix' => '',
        'strict' => true,
        'engine' => null,
    ],

8

このエラーの2つの解決策を見つけました

オプション1:

database / migrationsフォルダーのユーザーpassword_resetテーブルを開きます。

そして、メールの長さを変更するだけです:

$table->string('email',191)->unique();

オプション2:

app/Providers/AppServiceProvider.phpファイルを開き、boot()メソッド内でデフォルトの文字列長を設定します。

use Illuminate\Support\Facades\Schema;

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

7

1-/config/database.phpこれらの行に移動して見つけます

'mysql' => [
    ...,
    'charset' => 'utf8mb4',
    'collation' => 'utf8mb4_unicode_ci',
    ...,
    'engine' => null,
 ]

そしてそれらを次のように変更します:

'mysql' => [
    ...,
    'charset' => 'utf8',
    'collation' => 'utf8_unicode_ci',
    ...,
    'engine' => 'InnoDB',
 ]

2-php artisan config:cache laravelを再構成するために実行します

3-データベース内の既存のテーブルを削除してから、php artisan migrate再度実行します


1
これがlaravel 5.8の最良の答えです。ただし、作成済みのテーブルを削除する
Magige Daniel

しかし、ドキュメントによると、「utf8」は非推奨のutf8モードを使用しますか?
NoBugs


5

長さに制限を設定する代わりに、私は次のことを提案します。

内部:

config / database.php

mysqlの次の行を置き換えます。

'engine' => 'InnoDB ROW_FORMAT=DYNAMIC',

と:

'engine' => null,

4

これを修正するための移行ガイドで概説されているように、あなたがしなければならないことは、app/Providers/AppServiceProvider.phpファイルを編集し、起動メソッド内でデフォルトの文字列長を設定することです:

use Illuminate\Support\Facades\Schema;

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

注:最初に、ユーザーテーブル(ある場合)をデータベースから削除し、password_resetsテーブルをデータベースから削除し、ユーザーとpassword_resetsエントリを移行テーブルから削除する必要があります。

未解決の移行をすべて実行するには、migrateArtisanコマンドを実行します。

php artisan migrate

その後、すべてが正常に動作するはずです。


4

すでに指定したように、App / ProvidersのAppServiceProvider.phpに追加します

use Illuminate\Support\Facades\Schema;  // add this

/**
 * Bootstrap any application services.
 *
 * @return void
 */
public function boot()
{
    Schema::defaultStringLength(191); // also this line
}

詳細は以下のリンクで確認できます(「インデックスの長さとMySQL / MariaDB」を検索してくださいhttps://laravel.com/docs/5.5/migrations

しかし、それは私がすべてについて発表したものではありません!上記のことを行っても、別のエラーが発生する可能性がありますphp artisan migrateコマンドを実行すると長さが問題になるため、操作が途中で止まる可能性があります解決策は以下にあり、ユーザーテーブルが作成される可能性があります。残りがない、または完全に正しくない) ロールバックする必要があります。デフォルトのロールバックは機能しません。移行の操作が終了を好まなかったためです。データベースに新しく作成されたテーブルを手動で削除する必要があります。

以下のようにティンカーを使用してそれを行うことができます:

L:\todos> php artisan tinker

Psy Shell v0.8.15 (PHP 7.1.10  cli) by Justin Hileman

>>> Schema::drop('users')

=> null

私自身もusersテーブルに問題がありました。

その後、あなたは行ってもいいです

php artisan migrate:rollback

php artisan migrate


4

Mysql v5.5以降では、InnoDBがこの問題のないデフォルトのストレージエンジンであることは誰にも言えない解決策ですが、私のような多くの場合、以下のような古いMYISAMストレージエンジンを使用している古いmysql ini構成ファイルがいくつかあります。

default-storage-engine=MYISAM

これらすべての問題を引き起こしており、解決策は、一時的なハックを行う代わりに、Mysqlのini構成ファイルでdefault-storage-engineをInnoDBに一度変更することです。

default-storage-engine=InnoDB

あなたが上にある場合とMySQLのバージョン5.5以降、次にInnoDBはあなただけの削除、明示的に上記のようにそれを設定する必要はありませんので、デフォルトのエンジンであるdefault-storage-engine=MYISAM、それはあなたから存在する場合ini、ファイルとあなたが行ってもいいです。


ありがとう!これをlaravel 6とmysql 5.6で動作させるには、文字列の長さ、文字セット、照合順序の変更と組み合わせてこの提案を使用する必要がありました。うまくいけば、これは将来的に他の人を助けるでしょう。
キャスパーウィルクス

@CasperWilkesでは、文字列の長さや文字セットなどを行う必要はありません。Mysqlシステム変数をこのようにチェックし、ONにしshow global variables like 'innodb_large_prefix';てください。それはだ場合はOFF、あなたは確認することができ、このそれをオンにする方法の答えを。そして、ここに dev.mysql.comのinnodb_large_prefixに関する詳細があります。
Ali A. Dhillon

3

AppServiceProviderで変更する場合は、移行時にメールフィールドの長さを定義する必要があります。コードの最初の行を2行目に置き換えるだけです。

create_users_table

$table->string('email')->unique();
$table->string('email', 50)->unique();

create_password_resets_table

$table->string('email')->index();
$table->string('email', 50)->index();

変更が成功したら、移行を実行できます。
注:最初に、あなたは(あなたが持っている場合)を削除する必要があり、ユーザーテーブルpassword_resetsテーブルを移行テーブルからデータベースや削除、ユーザーとpassword_resetsエントリから。


3

Schema::defaultStringLength(191);デフォルトでは、データベースを破壊する可能性のあるすべての文字列の長さが定義されます。あなたはこのように行ってはいけません。

データベース移行クラスで特定の列の長さを定義するだけです。たとえば、CreateUsersTable次のようにクラスで「名前」、「ユーザー名」、「メール」を定義しています。

public function up()
    {
        Schema::create('users', function (Blueprint $table) {
            $table->increments('id');
            $table->string('name', 191);
            $table->string('username', 30)->unique();
            $table->string('email', 191)->unique();
            $table->string('password');
            $table->rememberToken();
            $table->timestamps();
        });
    }

1
Laravelのコアコードをいじらないようにしたいので、これは私にとって最も好ましい方法です。
Okiemute Omuta

2

Laravel 5.4がデフォルトのデータベース文字セットをutf8mb4に変更したため、これは一般的です。あなたがしなければならないことは、次のとおりです。クラス宣言の前にこのコードを配置して、App \ Providers.phpを編集します。

use Illuminate\Support\Facades\Schema;

また、これを「ブート」機能に追加します Schema::defaultStringLength(191);


2

データベースにまだデータが割り当てられていない場合は、次のようにします。

  1. app / Providers / AppServiceProvide.phpに移動して追加します

Illuminate \ Support \ ServiceProviderを使用します。

およびメソッドboot();の内部。

Schema :: defaultStringLength(191);

  1. 次に、データベースのレコード、exのユーザーテーブルを削除します。

  2. 次を実行する

php artisan config:cache

PHPの職人の移行


機能しましたが、追加する必要 use Illuminate\Support\Facades\Schema; use Illuminate\Support\ServiceProvider;があります。あなたがそれを修正することを願っています
Jimish Gamit

2

これを修正するための移行ガイドで概説されているように、あなたがしなければならないすべてはあなたのAppServiceProvider.phpファイルを編集し、ブートメソッド内でデフォルトの文字列長を設定します:

//edit your AppServiceProvider.php file contains in providers folder
use Illuminate\Support\Facades\Schema;

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

これがあなたを助けることを願っています。


2

次の行を変更usersしましたpassword_resets移行ファイルを変更しました。

古い: $table->string('email')->unique();

新着 : $table->string('email', 128)->unique();



1

StringLenghtを191に強制するのは本当に悪い考えだと思います。だから私は何が起こっているのかを理解するために調査します。

私はこのメッセージエラーに気づきました:

SQLSTATE [42000]:構文エラーまたはアクセス違反:1071指定されたキーが長すぎます。キーの最大長は767バイトです

MySQLのバージョンを更新した後、表示され始めました。そのため、PHPMyAdminでテーブルを確認したところ、作成されたすべての新しいテーブルが古いテーブルの照合utf8_unicode_ciではなく、照合utf8mb4_unicode_ciであることがわかりました。

私の教義の構成ファイルで、charsetがutf8mb4に設定されていることに気付きましたが、以前のすべてのテーブルはutf8で作成されたので、これがutf8mb4で機能するようになるいくつかの更新マジックだと思います。

これで簡単な修正は、ORM構成ファイルの行文字セットを変更することです。次に、開発モードの場合はutf8mb4_unicode_ciを使用してテーブルを削除し、削除できない場合は文字セットを修正します。

symfony 4の場合

config / packages / doctrine.yamlのcharset:utf8mb4charset:utf8に変更します

今、私の教義の移行は再びうまくいきます。


1

推奨される解決策は、 innodb_large_prefix、MySQLのオプションことです。これにより、その後の問題に巻き込まれることがなくなります。そして、これを行う方法は次のとおりです。

my.iniMySQL構成ファイルを開き、次の[mysqld]行をこのような行の下に追加します。

[mysqld]
innodb_file_format = Barracuda
innodb_large_prefix = 1
innodb_file_per_table = ON

その後、変更を保存し、MySQLサービスを再起動します。

必要に応じてロールバックし、移行を再実行します。


問題が解決しない場合に備えて、データベース構成ファイルに移動して設定します

'engine' => null,'engine' => 'innodb row_format=dynamic'

それが役に立てば幸い!


1

最初にローカルホストのデータベースのすべてのテーブルを削除します

ファイルconfig / database.phpのLaravelデフォルトデータベース(utf8mb4)プロパティを次のように変更します。

'charset' => 'utf8'、 'collat​​ion' => 'utf8_unicode_ci'、

その後、ローカルデータベースのプロパティutf8_unicode_ciを変更します。php artisan migrateそれは大丈夫です。


0

これに遭遇する可能性のある他の誰にとっても、私の問題は、タイプの列stringを作成->unsigned()していて、整数にするつもりだったときにそれを作成しようとしていることでした。


0

ここでのアプローチは、キー名(短いもの)を持つ2番目のパラメーターを渡すことでした:

$table->string('my_field_name')->unique(null,'key_name');

0

私はすでに持っていたのに(実際にはSchema :: defaultStringLength(191);にはすでに持っていた)。私のAppServiceProvider.phpファイル内。

その理由は、マイグレーションの1つで文字列値を191より大きい値に設定しようとしたためです。

Schema::create('order_items', function (Blueprint $table) {
    $table->primary(['order_id', 'product_id', 'attributes']);
    $table->unsignedBigInteger('order_id');
    $table->unsignedBigInteger('product_id');
    $table->string('attributes', 1000); // This line right here
    $table->timestamps();
});

1000を削除するか、191に設定すると、問題が解決しました。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.