Kesalahan Migrasi Laravel: Kesalahan sintaksis atau pelanggaran akses: 1071 Kunci yang ditentukan terlalu panjang; panjang kunci maks adalah 767 byte

178

Kesalahan migrasi pada Laravel 5.4 dengan php artisan make:auth

[Illuminate \ Database \ QueryException] SQLSTATE [42000]: Kesalahan sintaksis atau pelanggaran akses: 1071 Kunci yang ditentukan terlalu panjang; panjang kunci maks adalah 767 byte (SQL: alter tabl e usersadd unique users_email_unique( email))

[PDOException] SQLSTATE [42000]: Kesalahan sintaksis atau pelanggaran akses: 1071 Kunci yang ditentukan terlalu panjang; panjang kunci maks adalah 767 byte

absiddique hidup
sumber
3
Anda harus menjawab pertanyaan Anda dalam suatu jawaban. Tidak dalam pertanyaan. stackoverflow.com/help/self-answer
Can Vural
Terima kasih atas saran @ can-vural, saya lakukan.
absiddiqueLive

Jawaban:

283

Menurut dokumentasi resmi , Anda dapat menyelesaikan ini dengan mudah.

Tambahkan dua baris kode berikut ke 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 selalu menyimpan jumlah maksimum untuk bidang UTF8 yaitu 4 byte sehingga dengan 255 + 255 dengan SET DEFAULT CHARACTER Anda utf8mb4 COLLATE utf8mb4_unicode_ci; Anda melebihi batas panjang kunci maksimal 767. Oleh @scaisedge

absiddique hidup
sumber
3
Hati-hati dengan solusi ini. Jika Anda mengindeks bidang email misalnya, email yang disimpan hanya dapat memiliki panjang maksimal 191 karakter. Ini kurang dari negara RFC resmi.
shock_gone_wild
Ini bekerja dan merupakan solusi yang valid, tetapi saya hanya ingin menunjukkan, bahwa ada kemungkinan jebakan menggunakan pendekatan ini.
shock_gone_wild
Saya harap solusi ini tidak datang untuk menggigit pantat saya di masa depan, tetapi untuk saat ini, ini berhasil. Saya harus berhati-hati dengan cara saya mengindeks email.
deusofnull
4
mengapa tepatnya 191 karakter @absiddiqueLive
PseudoAj
121

Saya tidak tahu mengapa solusi di atas dan solusi resmi yang ditambahkan

Schema::defaultStringLength(191);

di AppServiceProvidertidak bekerja untuk saya. Apa yang berhasil adalah mengedit database.phpfile di configfolder. Cukup edit

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

untuk

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

dan itu akan berfungsi, meskipun Anda tidak akan dapat menyimpan karakter multibyte yang diperluas seperti emoji .

Saya melakukannya dengan Laravel 5.7. Semoga ini bisa membantu.

Koushik Das
sumber
5
Menggunakan rangkaian karakter ini hanya akan memungkinkan Anda untuk menyimpan ASCII Standar, dan bukan multibyte karakter khusus seperti yang berasal dari Arab, Ibrani, sebagian besar skrip Eropa, dan tentu saja emoji. lihat juga stackoverflow.com/a/15128103/4233593
Jeff Puckett
7
Saya pikir Anda melewatkan bagian ini use Illuminate\Support\Facades\Schema;di atas.
pimpace
@KoushikDas versi Laravel apa yang Anda gunakan?
pimpace
Sekarang saya menggunakan 6.0. Saya pikir saya melakukannya pada awalnya dengan 5,7 atau 5,6 mungkin.
Koushik Das
2
The utf8mb4pemeriksaan ada karena suatu alasan, saya sarankan untuk menggunakannya jika Anda bisa.
Nyalakan
85

Saya hanya menambahkan jawaban ini di sini karena itu quickestsolusi bagi saya. Cukup setel mesin database default ke 'InnoDB'on

/config/database.php

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

kemudian jalankan php artisan config:cacheuntuk menghapus dan menyegarkan cache konfigurasi

Dexter Bengil
sumber
1
Ini harus menjadi jawaban / solusi resmi untuk pertanyaan ini ... Terima kasih
Syamsoul Azrien
1
Ini adalah solusi aktual, yang lain adalah solusi
Luís Cunha
3
tapi apa logika di balik ini
Zulfiqar Tariq
1
Itu solusi yang tepat. Tapi mengapa tidak dimasukkan dalam instalasi default.
Ankit Chauhan
38

Dalam AppServiceProvider.php, Anda memasukkan kode ini di bagian atas file.

use Illuminate\Support\Facades\Schema;

public function boot()
{
Schema::defaultStringLength(191);
}
pengguna7688086
sumber
Terima kasih membantu saya
The Dead Man
24

Masalah ini disebabkan di Laravel 5.4 oleh versi database.

Menurut dokumen (di Index Lengths & MySQL / MariaDBbagian):

Laravel menggunakan utf8mb4karakter yang ditetapkan secara default, yang mencakup dukungan untuk menyimpan "emoji" dalam database. Jika Anda menjalankan versi MySQL yang lebih lama dari rilis 5.7.7 atau MariaDB yang lebih lama dari rilis 10.2.2, Anda mungkin perlu mengkonfigurasi secara manual panjang string default yang dihasilkan oleh migrasi agar MySQL dapat membuat indeks untuk mereka. Anda dapat mengonfigurasi ini dengan memanggil Schema::defaultStringLengthmetode di dalam AppServiceProvider.

Dengan kata lain, di <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);
}

// ...

}

Tetapi seperti komentar pada jawaban lain mengatakan:

Hati-hati dengan solusi ini. Jika Anda mengindeks bidang email misalnya, email yang disimpan hanya dapat memiliki panjang maksimal 191 karakter. Ini kurang dari negara RFC resmi.

Jadi dokumentasi juga mengusulkan solusi lain:

Atau, Anda dapat mengaktifkan innodb_large_prefixopsi untuk database Anda. Lihat dokumentasi database Anda untuk instruksi tentang cara mengaktifkan opsi ini dengan benar.

Esteban Herrera
sumber
16

Untuk seseorang yang tidak ingin berubah AppServiceProvider.php. (Menurut saya, itu ide buruk untuk berubah AppServiceProvider.phphanya untuk migrasi)

Anda dapat menambahkan kembali panjang data ke file migrasi database/migrations/seperti di bawah ini:

create_users_table.php

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

create_password_resets_table.php

$table->string('email',128)->index();
helloroy
sumber
Ini bisa menjadi masalah karena email dapat mencapai 255 (ish) karakter
Half Crazed
Anda benar @HalfCrazed, tetapi saya menyarankan jawaban ini stackoverflow.com/questions/1297272
helloroy
masalah saya sebenarnya dipecahkan oleh solusi ini. Field saya bukan email.
Tharaka Devinda
11

Jika Anda menghadapi kesalahan ini saat bekerja di laravel saat menggunakan perintah: php artisan migrate maka Anda hanya menambahkan 2 baris dalam file: app-> Providers-> AppServiceProvider.php

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

silakan periksa gambar ini . lalu jalankan php artisan migrateperintah lagi.

Abdul Rasheed
sumber
1
sangat penting untuk menambahkan 'gunakan Skema;'. Jadi ini adalah jawaban terbaik
hxwtch
Anda juga dapat melakukan ini dalam satu baris dengan menambahkan garis miring '\' sebelum baris ke-2 seperti ini\Schema::defaultStringLength(191);
Tahir Afridi
10

Saya menambahkan dua solusi yang bekerja untuk saya.

Solusi pertama adalah :

  1. Buka file database.php insde config dir / folder.
  2. Edit 'engine' => null,ke'engine' => 'InnoDB',

    Ini berhasil untuk saya.

Solusi kedua adalah:

  1. Buka file database.php insde config dir / folder.
    2. Edit
    'charset' => 'utf8mb4', 'collation' => 'utf8mb4_unicode_ci',
    ke

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


Semoga berhasil

Arslan Ahmad
sumber
10

perbarui & sisipkan baris ini di app / Penyedia / 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
}
Anjani Barnwal
sumber
8

Saya telah memecahkan masalah ini dan mengedit file config-> database.php agar menyukai database saya ('charset' => 'utf8') dan ('collation' => 'utf8_general_ci') , jadi masalah saya adalah memecahkan kode sebagai mengikuti:

'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,
    ],
Ahmad Shakib
sumber
8

Saya telah menemukan dua solusi untuk kesalahan ini

PILIHAN 1:

Buka tabel user dan password_reset Anda di folder database / migrasi

Dan cukup ubah panjang email:

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

PILIHAN 2:

Buka app/Providers/AppServiceProvider.phpfile Anda dan di dalam boot()metode setel panjang string default:

use Illuminate\Support\Facades\Schema;

public function boot()
{
    Schema::defaultStringLength(191);
}
Udhav Sarvaiya
sumber
7

1- Buka /config/database.phpdan temukan garis-garis ini

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

dan mengubahnya menjadi:

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

2- Jalankan php artisan config:cacheuntuk mengkonfigurasi ulang laravel

3 - Hapus tabel yang ada di database Anda dan kemudian jalankan php artisan migratelagi

mohammad asghari
sumber
1
ini adalah jawaban terbaik untuk laravel 5.8. Tapi hapus tabel yang sudah dibuat
Magige Daniel
tetapi menurut dokumentasi "utf8" akan menggunakan mode utf8 yang sudah tidak digunakan lagi?
NoBugs
5

Dalam file AppServiceProvider.php :

 use Illuminate\Support\Facades\Schema;

public function boot()
{
    Schema::defaultStringLength(191);
}
Uddyan Semwal
sumber
5

Alih-alih menetapkan batas panjang saya akan mengusulkan yang berikut, yang telah bekerja untuk saya.

Dalam:

config / database.php

ganti baris ini untuk mysql:

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

dengan:

'engine' => null,
Siddique Noor-A-Alam
sumber
4

Seperti yang dijelaskan dalam panduan Migrasi untuk memperbaikinya, yang harus Anda lakukan adalah mengedit app/Providers/AppServiceProvider.phpfile Anda dan di dalam metode boot, tentukan panjang string default:

use Illuminate\Support\Facades\Schema;

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

Catatan: pertama Anda harus menghapus (jika ada) tabel pengguna , tabel password_resets dari database dan menghapus entri pengguna dan password_resets dari tabel migrasi .

Untuk menjalankan semua migrasi luar biasa Anda, jalankan migrateperintah Artisan:

php artisan migrate

Setelah itu semuanya harus berfungsi seperti biasa.

Dexter Bengil
sumber
4

Seperti yang sudah ditentukan, kami menambahkan ke AppServiceProvider.php di App / Penyedia

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

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

Anda dapat melihat detail lebih lanjut di tautan di bawah (cari "Panjang Indeks & MySQL / MariaDB") https://laravel.com/docs/5.5/migrations

TETAPI BUKAN BUKANLAH itu yang saya terbitkan! masalahnya bahkan ketika melakukan hal di atas Anda kemungkinan akan mendapatkan kesalahan lain (saat itulah Anda menjalankan php artisan migrateperintah dan karena masalah panjangnya, operasi kemungkinan akan macet di tengah. solusinya di bawah , dan tabel pengguna kemungkinan dibuat tanpa istirahat atau tidak sepenuhnya benar) kita perlu memutar kembali . gulungan standar tidak akan berfungsi. karena operasi migrasi tidak suka selesai. Anda perlu menghapus tabel yang baru dibuat dalam database secara manual.

kita bisa melakukannya menggunakan tinker seperti di bawah ini:

L:\todos> php artisan tinker

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

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

=> null

Saya sendiri punya masalah dengan tabel pengguna.

setelah itu kamu baik-baik saja

php artisan migrate:rollback

php artisan migrate

Mohamed Allal
sumber
4

Solusinya tidak ada yang memberi tahu adalah bahwa dalam Mysql v5.5 dan kemudian InnoDB adalah mesin penyimpanan default yang tidak memiliki masalah ini, tetapi dalam banyak kasus seperti milik saya ada beberapa file konfigurasi mysql ini lama yang menggunakan mesin penyimpanan MYISAM lama seperti di bawah ini.

default-storage-engine=MYISAM

yang menciptakan semua masalah ini dan solusinya adalah perubahan default-storage-mesin untuk InnoDB di MySQL ini Penyanyi file konfigurasi sekali dan untuk semua bukannya melakukan hacks sementara.

default-storage-engine=InnoDB

Dan jika Anda menggunakan MySql v5.5 atau lebih baru maka InnoDB adalah mesin default sehingga Anda tidak perlu mengaturnya secara eksplisit seperti di atas, hapus saja default-storage-engine=MYISAMjika ada dari inifile Anda dan Anda siap untuk menggunakannya.

Ali A. Dhillon
sumber
Terima kasih! Saya harus menggunakan saran ini bersamaan dengan perubahan panjang string, charset, dan collation untuk membuatnya bekerja dengan laravel 6 dan mysql 5.6. Semoga ini membantu orang lain di masa depan.
Casper Wilkes
@CasperWilkes Anda tidak perlu melakukan hal yang panjang string, charset stuff. Periksa variabel sistem Mysql Anda seperti ini show global variables like 'innodb_large_prefix';harus ON . Jika MATI maka Anda dapat memeriksa jawaban ini tentang cara mengaktifkannya. Dan di sini adalah informasi lebih lanjut tentang innodb_large_prefix di dev.mysql.com.
Ali A. Dhillon
3

Jika Anda ingin mengubah di AppServiceProvider maka Anda perlu menentukan panjang bidang email dalam migrasi. ganti saja baris kode pertama ke baris kedua.

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();

Setelah perubahan berhasil, Anda dapat menjalankan migrasi.
Catatan: pertama Anda harus menghapus (jika ada) tabel pengguna , tabel password_resets dari database dan menghapus entri pengguna dan password_resets dari tabel migrasi.

Chintan Kotadiya
sumber
3

Schema::defaultStringLength(191);akan menentukan panjang semua string 191 secara default yang dapat merusak database Anda. Anda tidak harus pergi dengan cara ini.

Cukup tentukan panjang kolom spesifik apa pun di kelas migrasi basis data. Sebagai contoh, saya mendefinisikan "nama", "nama pengguna" dan "email" di CreateUsersTablekelas seperti di bawah ini:

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();
        });
    }
Fatema T. Zuhora
sumber
1
Ini paling disukai bagi saya karena saya lebih suka tidak mengubah kode inti Laravel.
Okiemute Omuta
2

Ini umum karena Laravel 5.4 mengubah charater database default yang ditetapkan ke utf8mb4. Yang harus Anda lakukan adalah: edit Aplikasi \ Providers.php Anda dengan meletakkan kode ini sebelum deklarasi kelas

use Illuminate\Support\Facades\Schema;

Juga, tambahkan ini ke fungsi 'boot' Schema::defaultStringLength(191);

Harta
sumber
2

Jika Anda belum memiliki data yang ditugaskan pada basis data Anda, lakukan hal berikut:

  1. Buka aplikasi / Penyedia / AppServiceProvide.php dan tambahkan

gunakan Illuminate \ Support \ ServiceProvider;

dan di dalam metode boot ();

Schema :: defaultStringLength (191);

  1. Sekarang hapus catatan dalam database Anda, tabel pengguna untuk mantan.

  2. jalankan yang berikut ini

php artisan config: cache

php tukang bermigrasi

Levinski Polish
sumber
Itu berhasil tetapi perlu menambahkan use Illuminate\Support\Facades\Schema; use Illuminate\Support\ServiceProvider;sudah ada di sana. Semoga Anda memperbaikinya
Jimish Gamit
2

Seperti yang diuraikan dalam panduan Migrasi untuk memperbaikinya, yang harus Anda lakukan adalah mengedit file AppServiceProvider.php Anda dan di dalam metode boot, tentukan panjang string default:

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

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

Semoga ini bisa membantu Anda..mereka ..

Rohit Saini
sumber
2

Saya baru saja memodifikasi baris berikut dalam usersdan password_resetsfile migrasi.

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

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

Mahesh Gaikwad
sumber
1

Saya pikir untuk memaksa StringLenght ke 191 adalah ide yang sangat buruk. Jadi saya menyelidiki untuk memahami apa yang sedang terjadi.

Saya perhatikan bahwa pesan ini salah:

SQLSTATE [42000]: Kesalahan sintaksis atau pelanggaran akses: 1071 Kunci yang ditentukan terlalu panjang; panjang kunci maks adalah 767 byte

Mulai muncul setelah saya memperbarui versi MySQL saya. Jadi saya sudah memeriksa tabel dengan PHPMyAdmin dan saya perhatikan bahwa semua tabel baru dibuat dengan collation utf8mb4_unicode_ci, bukan utf8_unicode_ci untuk yang lama.

Dalam file konfigurasi doktrin saya, saya perhatikan bahwa charset diatur ke utf8mb4, tetapi semua tabel saya sebelumnya dibuat di utf8, jadi saya kira ini adalah beberapa pembaruan ajaib yang mulai berfungsi pada utf8mb4.

Sekarang perbaikan yang mudah adalah dengan mengubah baris charset di file konfigurasi ORM Anda. Kemudian untuk menjatuhkan tabel menggunakan utf8mb4_unicode_ci jika Anda dalam mode dev atau memperbaiki charset jika Anda tidak bisa menjatuhkannya.

Untuk Symfony 4

ubah charset: utf8mb4 ke charset: utf8 di config / paket / doctrine.yaml

Sekarang migrasi doktrin saya bekerja kembali dengan baik.

Kaizoku Gambare
sumber
1

Solusi yang disarankan adalah mengaktifkan innodb_large_prefixopsi MySQL sehingga Anda tidak akan mendapatkan masalah berikutnya. Dan inilah cara melakukannya:

Buka my.inifile konfigurasi MySQL dan tambahkan baris di bawah di bawah [mysqld]baris seperti ini.

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

Setelah itu, simpan perubahan Anda dan mulai kembali layanan MySQL Anda.

Kembalikan jika Anda perlu dan jalankan kembali migrasi Anda.


Untuk berjaga-jaga jika masalah Anda masih berlanjut, buka file konfigurasi database Anda dan atur

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

Semoga ini bisa membantu!

Sammie
sumber
1

pertama-tama hapus semua tabel database di localhost

Ubah properti Laravel default database (utf8mb4) di file config / database.php menjadi:

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

setelah itu Mengubah properti database lokal saya utf8_unicode_ci. tukang php bermigrasi itu ok.

Goldman.Vahdettin
sumber
0

Bagi siapa pun yang mungkin mengalami ini, masalah saya adalah bahwa saya membuat kolom tipe stringdan mencoba membuatnya ->unsigned()ketika saya bermaksud untuk menjadi bilangan bulat.

Brynn Bateman
sumber
0

Yang didekati yang bekerja di sini adalah lulus param kedua dengan nama kunci (yang pendek):

$table->string('my_field_name')->unique(null,'key_name');
Tiago Gouvêa
sumber
0

Saya mendapatkan kesalahan ini meskipun saya sudah punya (sebenarnya karena saya sudah punya) Skema :: defaultStringLength (191); dalam file AppServiceProvider.php saya.

Alasannya adalah karena saya mencoba menetapkan nilai string di salah satu migrasi saya ke nilai yang lebih tinggi dari 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();
});

Menghapus 1000 atau mengaturnya ke 191 memecahkan masalah saya.

Jacey
sumber