Laravel taşıma: belirtilse bile benzersiz anahtar çok uzun


166

Laravel'de bir kullanıcı tablosunu taşımaya çalışıyorum. Geçişimi çalıştırdığımda şu hatayı alıyorum:

[Illuminate \ Database \ QueryException] SQLSTATE [42000]: Sözdizimi hatası veya erişim ihlali: 1071 Belirtilen anahtar çok uzun; maksimum anahtar uzunluğu 767 bayttır (SQL: tablo değiştirme usersbenzersiz kullanıcılar ekle_email_uniq ( email))

göçüm şu şekildedir:

Schema::create('users', function(Blueprint $table)
{
    $table->increments('id');
    $table->string('name', 32);
    $table->string('username', 32);
    $table->string('email', 320);
    $table->string('password', 64);
    $table->string('role', 32);
    $table->string('confirmation_code');
    $table->boolean('confirmed')->default(true);
    $table->timestamps();

    $table->unique('email', 'users_email_uniq');
});

Bazı googling sonra Taylor bu hata raporu geldi indeks anahtar 2 parametre olarak belirtebilirsiniz unique(), hangi yaptım. Hala hata veriyor. Burada neler oluyor?


E-posta için neden 320 karakter kullanıyorsunuz? Bu senin sorunun olabilir.
Antonio Carlos Ribeiro

1
Gerçekten sorun buydu, neden olduğu hakkında bir fikrim yok. Ama evet, haklısın, neden her alan için karakter uzunluğunu belirttiğimi bilmiyorum. Bu sınırları kaldırdık
Harry

Hiç kimsenin e-posta ve voila hash'ını içeren sabit uzunluklu alanı kullanmayı kimsenin önermemesi komiktir - sorun, herhangi bir çerçeve ve herhangi bir ilişkisel veritabanı için sonsuza kadar çözüldü. Çünkü benzersizliği garanti ediyoruz - sayı aralığının yeterince büyük olduğu (ve sha1 / sha256 için) değişken uzunluklu girdilerin sabit sayı gösterimini kullanarak.
NB


Yanıtlar:


280

E-postanız için daha küçük bir uzunluk belirtin:

$table->string('email', 250);

Aslında bu varsayılan değerdir:

$table->string('email');

Ve iyi olmalısın.

Laravel 5.4 için bu Laravel 5.4'te bir çözüm bulabilirsiniz : Belirtilen anahtar çok uzun hataydı, Laravel News post:

Bunu düzeltmek için Geçişler kılavuzunda belirtildiği gibi, yapmanız gereken tek şey AppServiceProvider.php dosyanızı düzenlemek ve önyükleme yönteminin içinde varsayılan bir dize uzunluğu ayarlamaktır:

use Illuminate\Database\Schema\Builder;


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

6
Maksimum olası e-posta uzunluğu 254muhtemelen bunu akılda tutmaya değer , bu yüzden muhtemelen bu durumda doğrulayıcı kullanarak benzersizliği doğrularım.
Sebastian Sulinski

12
İçin laravel 5.4 , kullanım \Illuminate\Database\Schema\Builder::defaultStringLength(191);doğru işlev referans yolu için
WebCoder

5
AppServiceProvider.php dosyasında yapılandırma yaptıktan sonra bu sorun devam ediyor. Sadece kafam karıştı. Neden? Sunucu, veritabanı ve her şeyi yeniden başlattım ama yine de. Lütfen yardım et.
Koushik Das

3
Dizine alınan sütunun uzunluğunu 767 bayt sınırına göre ayarlamanız gerekir. VARCHAR'ın her uzunluk birimi için 1, 2 veya 4 bayta sahip olabileceğini unutmayın. Örnek: utf8_mb4 (4 bayt) -> 767/4 = 191. Aksi takdirde X <85 (1 bayt) = O (85) ile VARCHAR (X) için utf8_general_ci veya X> = 86 (2 ile VFAR_AR (X) için utf8_general_ci bayt) -> 767/2 = 383. Birden çok sütun dizinindeki diğer sütun uzunluklarını da göz önünde bulundurun.
Jackie Degl'Innocenti

2
Ayrıca, tüm dize sütunları için varsayılan bir uzunluk belirterek, geçiş dosyalarındaki belirli sütunun uzunluğunu doğrudan düzenlemek isteyebilirsiniz, çünkü tüm sütunlar herhangi bir dizinde olmadığı için bu kısıtlamaya ihtiyaç duymaz. $ Tablo-> string ( 'column_name, 191);
Jackie Degl'Innocenti

109

Güncelleme 1

İtibariyle laravel 5.4 bu değişiklikler gerekli tükendi.

Laravel 5.4 varsayılan olarak utf8mb4 karakter kümesini kullanır ve bu veritabanında "emoji" depolamak için destek içerir. Uygulamanızı Laravel 5.3'ten yükseltiyorsanız, bu karakter kümesine geçmeniz gerekmez.

Güncelleme 2

Mevcut üretim MariaDB sürümleri bu ayarı varsayılan olarak dünya çapında DESTEKLEMEZ . Bu uygulanan varsayılan olarak mariadb 10.2.2+ .

Çözüm

Ve future için kasıtlı olarak doğru gelecekteki varsayılanı (Laravel 5.4'ten başlayarak) kullanmak istiyorsanız UTF8 çoklu bayt utf8mb4desteği 😀 için veritabanı yapılandırmanızı düzeltmeye başlayın.

Laravel'de şunları config/database.phptanımlayın:

'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
'engine' => 'InnoDB ROW_FORMAT=DYNAMIC',

DYNAMICuzun anahtar indekslerinin saklanmasını sağlar .

Sunucu ayarları (varsayılan olarak MySQL 5.7.7+ / MariaDB 10.2.2+ sürümüne dahildir):

[mysqld]
# default character set and collation
collation-server = utf8mb4_unicode_ci
character-set-server = utf8mb4

# utf8mb4 long key index
innodb_large_prefix = 1
innodb_file_format = barracuda
innodb_file_format_max = barracuda
innodb_file_per_table = 1

Müşteriler için:

[mysql]
default-character-set=utf8mb4

Ve sonra DUR MySQL / mariadb sunucusu. Bundan sonra BAŞLAT. Sıcak RESTART çalışmayabilir.

sudo systemctl stop mysqld
sudo systemctl start mysqld

Artık UTF8 desteği ile Laravel 5.x var.


3
Bu MySQL 5.5 ile yeterince iyi uyandırılabilir (yeniden yapılandırmaya çalışmadı). 5.7 (muhtemelen 5.6) herhangi bir yeniden yapılandırmaya gerek olmadan çalıştı. 5.7, vanilya yapılandırmasına sahip varsayılan bir Community Server dağıtımıydı.
Pjotr

Bahsettiğim gibi database.php dosyamdaki motoru değiştirdim ama hala bir soruna neden olan row = compact ile tablolar oluşturuyor. Tam olarak anlamadım, database.php dosyasında bu değişikliği yapmanın yeterli olmadığını ve my.cnf dosyasında değişiklik yapmanın gerekli olduğunu mu söylüyorsunuz?
vesperknight

Sadece database.phpyapılandırma dosyasında değişiklik yapmak yeterlidir ve yerel Laravel projesini etkileyecektir. deleteDeğişiklik yapmadan önce veritabanını oluşturduğunuzdan ve yeni ayarlarla oluşturduğunuzdan emin olun . my.cnfYapılandırma dosyasını yalnızca genel sunucu tarafı değişiklikleri için değiştirmeniz gerekir (şu anda tüm yeni yüklemeler kullanılmaktadır utf8mb4).
hakemi

Veya - başka bir alan ekleyin, e-postanın karmasını hesaplayın, alanı benzersiz yapın, sorunu sonsuza kadar çözün, veritabanı başlatma değişkenleriyle uğraşmaktan kaçının.
NB

Herhangi biri Doktrin 2'yi kullanıyorsaoptions={"row_format"="DYNAMIC"} , @Tableek açıklamanıza ileterek ROW_FORMAT'ı ayarlayabilirsiniz .
Albert221

50

Laravel 5.4 üzerinde veya güncellemeniz varsa Bu benim için çalıştı;

Sadece 1 değişiklik. AppServiceProvider.php içinde

use Illuminate\Support\Facades\Schema;

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

Taşıma kılavuzunda belirtildiği gibi https://laravel.com/docs/master/migrations#creating-indexes


Bunu göçün kendisinde yaptım.
Amirmasoud

7
Bu (muhtemelen) çünkü her karakter tam olarak 4 bayt alır ve maksimum anahtar uzunluğu karakter değil bayt olarak ölçülür. Anahtar uzunluğu 191 * 4 = 764 bayt olacak, sadece veritabanının destekleyeceği maksimum 767 baytın altındaki bir smidgen. Çözümler burada paylaşılan bilgilere katkıda bulunacaklarsa ve sadece "prosedürler" sağlamazlarsa IMO'nun açıklamalarına ihtiyaç duyarlar. Ancak yine de kullanışlı bir düzeltme.
Jason

33

Benim yaptığım gibi ama başka bir sebeple bu cevabı tökezleyen varsa, Laravel DB karakter / harmanlama kontrol edebilirsiniz.

Bir uygulama (Snipe-IT) yükledim ve Laravel veritabanı yapılandırmasını aşağıdakileri kullanacak şekilde yapılandırdım:

'charset' => 'utf8mb4',
'collation' => 'utf8mb4_general_ci',

mb4Antonio'nun cevabının sorunun gerçek çözümü olduğuna inanmasına rağmen, her iki dizeden de kaldırmak sorunu düzeltti.



16

Mb4'ü charset'ten ve harmanlamayı config / database.php'den kaldırın, sonra başarıyla yürütülür.
'charset' => 'utf8',
'harmanlama' => 'utf8_unicode_ci',


15

Laravel 5.6 için
Bu çözüm sorunumu çözmek Aşağıdaki kodu bulmak
gidinconfig/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' => 'utf8mb4',
    'collation' => 'utf8mb4_unicode_ci',
    'prefix' => '',
    'strict' => true,
    'engine' => null,
],

Bu iki alanı değiştir

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

Bununla

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

14

Aynı sorunla karşılaştım ve uygulamam / database.php dosyasına aşağıdaki iki satırı ekleyerek düzelttim.

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

Dosyam aşağıdaki gibi görünüyor:

<?php

return [

    /*
    |--------------------------------------------------------------------------
    | Default Database Connection Name
    |--------------------------------------------------------------------------
    |
    | Here you may specify which of the database connections below you wish
    | to use as your default connection for all database work. Of course
    | you may use many connections at once using the Database library.
    |
    */

    'default' => env('DB_CONNECTION', 'mysql'),

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

    ......

2
Laravel'e yeni bir sürüm yüklediyseniz. Lütfen 'mb4'ü utf8mb4 & utf8mb4_unicode_ci & config / database.php'den
kaldırın

13

Laravel 5.4 için dosyayı düzenleyin

App \ Hizmeti Şirketi \ AppServiceProvider.php

use Illuminate\Support\Facades\Schema;

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

7
File: config/database.php
change the following
FROM ->
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',

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

1
Bu soruya cevap verebilirken, bu cevabın sorunu çözmeye nasıl yardımcı olabileceğine dair bir açıklama eklemek daha iyidir. Lütfen daha fazla bilgi için nasıl iyi bir cevap yazarım? Başlıklı konuyu okuyun .
Roshana Pitigala

6

aynı problemim vardı ve bir wamp kullanıyorum

Çözüm: Açık dosya: config / database.php

'engine' => null, => 'engine' => 'InnoDB',

Teşekkürler


Önceki cevapların hiçbiri benim için çalıştı, ama bu bir cazibe gibi çalıştı! Ve bu çok mantıklı, Laravel DB motorunun önceki sürümlerinin varsayılan olarak InnoDB olarak ayarlandığına inanıyorum, bu nedenle daha önce bu hatalarla karşılaşmadık.
Sasa Blagojevic

evet diğer cevaplar ve bu da bir çift yapmak gerekiyordu.
Andrew

6

Config / database.php dosyasında burada:

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

Bu satırı şu şekilde değiştirin:

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

5

İçin laravel> = 5.6 kullanıcıları

AppServiceProvider.phpDosya aç

Aşağıdaki sınıfı kullanın

use Illuminate\Support\Facades\Schema;

Sonra iç bootyöntem aşağıdaki satırı ekleyin

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

4

Göçün kendisine ekledim

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

Evet, her geçişte bunu düşünmem gerektiğini biliyorum ama tamamen ilgisiz bir servis sağlayıcıya gizlememeyi tercih ederim


4

Birisi yaptıktan sonra bile bu sorunu yaşıyorsa, yukarıda belirtilen değişiklikler. Örneğin, benim durumumda aşağıdaki değişiklikleri yaptım,

namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Schema;

class AppServiceProvider extends ServiceProvider
{
  /**
   * Register any application services.
   *
   * @return void
   */
   public function register()
   {
      //
   }

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

Ancak iki nedenden dolayı hemen işe yaramaz. Birincisi laravel yerine lümen kullanıyorsanız, önce bu satırı app.php dosyanızda açmanız gerekebilir.

$app->register(App\Providers\AppServiceProvider::class);

Ve sonra artisan komutuyla tekrar geçiş komut dosyasını oluşturmanız gerekir,

php artisan make:migration <your_table_name>

Şu andan beri yalnızca ServiceProvider'da yaptığınız değişiklikler çalışacak.


4

laravel 5.7 için bu kodu appserviceprovider.php dosyasına yazın

  use Illuminate\Support\Facades\Schema;

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

2

Karakter setini 'utf8mb4' yerine 'utf8' olarak değiştirin ve

'utf8mb4_unicode_ci' için 'utf8_unicode_ci'

config / database.php dosyasında

Benim için çalıştı.


2

Laravel, utf8mb4varsayılan olarak "emojileri" veritabanında saklamak için destek içeren karakter kümesini kullanır . 5.7.7 sürümünden daha eski bir MySQL sürümü veya 10.2.2 sürümünden daha eski bir MariaDB sürümü kullanıyorsanız, MySQL'in kendileri için dizin oluşturması için geçişler tarafından oluşturulan varsayılan dize uzunluğunu el ile yapılandırmanız gerekebilir. Bunu, aşağıdakiler Schema::defaultStringLengthdahilindeki yöntemi çağırarak yapılandırabilirsiniz AppServiceProvider:

use Illuminate\Support\Facades\Schema;

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

Kontrol edebilirsiniz

https://laravel-news.com/laravel-5-4-key-too-long-error https://laravel.com/docs/5.5/migrations#indexes


teşekkürler, benim için çalışıyor. laravel 5.6.23 ile mamp mysql
bluesky

2

Çünkü Laravel 5.4 , emojileri depolamayı destekleyen utf8mb4 kullanıyor .

Bunu uygulamanıza ekleyin \ Providers \ AppServiceProvider.php

use Illuminate\Support\Facades\Schema;

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

ve gitmek için iyi olmalısın.


2

Laravel 5.4 sürümünde veya son sürümü kullanıyorsanız veya güncelleştirilmişse çalışır;
AppServiceProvider.php dosyasında yalnızca 1 değişiklik

use Illuminate\Support\Facades\Schema;

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

1

Kaçırdığım bir şeye işaret etmek istiyorum ...

Laravel'de yeniyim ve "Use Illuminate ....." i kopyalamamıştım çünkü gerçekten dikkat etmedim, çünkü fonksiyon açılışının hemen üstünde bir kullanım ifadesi var .

Umarım herkese yardım eder

**use Illuminate\Support\Facades\Schema;**

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

Ayrıca, herhangi bir Cephe ile ön ek yapabilirsiniz\
Ohgodwhy

1

Bir sorun yaşadım, 'config / database' yapılandırmasını değiştirdim

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

aynı modeli veritabanında tutmak.

Sonra emir verdim

php artisan migrate

1

24 Ekim 2016'da Laravel'in yazarı Taylor Otwell Twitter'da

"utf8mb4", daha iyi emoji desteği için Laravel 5.4'te ayarlanan varsayılan MySQL karakteridir. Ot Taylor Otwell Twitter Gönderi

5.4 sürümünden önce karakter seti utf8

Bu yüzyıl boyunca birçok web uygulaması, kullanıcılarının sohbet etmelerine izin vermek için sohbet veya bir tür platform içerir ve birçok kişi emoji veya gülen yüz kullanmayı sever. ve bu daha fazla alanın depolanmasını gerektiren ve sadece karakterutf8mb4 olarak kullanılması mümkün olan bir tür süper karakter . Sadece uzay amacıyla göç etmelerinin nedeni budur .utf8mb4

Eğer yukarı bakarsan Illuminate\Database\Schema\Buildersınıfta bunu göreceksiniz $defaultStringLengthayarlandığında 255 ve bakmanız procede ki değiştirmeye SchemaCephe ve çağrı defaultStringLengthyöntemi ve yeni uzunluğunu geçmektedir.

bu değişikliği gerçekleştirmek için AppServiceProvidersınıfınızdaki app \ providers alt dizini altındaki bu yöntemi çağırın

class AppServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        // all other code ...

        Schema::defaultStringLength(191); 
    }
    // and all other code goes here
}

191 değerini sadece MySQL'i 767 bayt desteklediğinden ve 767 / 4alacağınız her çok baytlı karakter tarafından alınan bayt sayısından dolayı kullanmanızı öneririz 191.

Burada daha fazla bilgi edinebilirsiniz Tablo Sütunu Sayısı ve Satır Boyutu üzerindeki utf8mb4 Karakter Kümesi (4 Bayt UTF-8 Unicode Kodlama) Sınırları


191Sihirli sayıyı açıklayan tek cevap bu .
Illya Moskvin


1

Gitmek config/database.phpve karakter ve harmanlamayı utf8mb4 yerine utf8 olarak değiştirmek

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

Benim sorunum bu yöntemi kullanarak çözüldü, iyi şanslar dostum!


0

MySQL 5.7.7+ veya MariaDB 10.2.2+ kullanıyorsanız bu sorunu yaşamayacaksınız.

Brew'i kullanarak Mac'inizdeki MariaDB'yi güncellemek için önce mevcut olanın bağlantısını brew unlink mariadbkaldırın : ve ardındanbrew install mariadb --devel

Kurulum tamamlandıktan sonra çalışan hizmeti durdurun / başlatın: brew services stop mariadb brew services start mariadb

Mevcut geliştirici sürümü 10.2.3'tür. Kurulum bittikten sonra artık bunun için endişelenmenize gerek kalmayacak ve utf8mb4'ü (şimdi Laravel 5.4'te varsayılan) kullanmadan utf8'e dönmeden veya AppvelServiceProvider'ı Laravel belgelerinde önerildiği gibi düzenlemeden kullanabilirsiniz: https: // laravel .com / docs / master / sürümler # laravel-5.4 (Aşağıya kaydır: Varsayılan Geçiş Dizesi Uzunluğu )


0

Yeni kurulan MariaDB 10.2.4 RC, yeni boş Laravel 5.4 projesi ateşledi ve varsayılan geçiş (varchar (255) sütunlar) çalışır.

DB conf ve Laravael'i değiştirmeye gerek yok config/database.php. Böylece, skorcunun 10.2.2+ için varsayılan davranış hakkında belirttiği gibi.


0

Tüm diğerleri iyi açıklanmıştır Anwser aşağıdaki bağlantıda daha fazla ayrıntı görebilirsiniz (anahtar 'Dizin Uzunlukları ve MySQL / MariaDB "ile arama) https://laravel.com/docs/5.5/migrations

ANCAK, bu cevabın ne olduğu değil! şey yukarıda yapmakla bile başka bir hata almak gibi olacak (o zaman başlatmak php artisan migratekomutu gibi ve uzunluk sorunu nedeniyle, ortasında sıkışmış gibi işlem. çözüm feryat ve kullanıcı tablosu olmadan oluşturulan gibi gerisi ya da tamamen doğru değil) bac k'yi yuvarlamamız gerekiyor . varsayılan geri alma işlemi yapılmaz. çünkü göç operasyonu bitirmek istemiyordu. veritabanında yeni oluşturulan tabloları el ile silmeniz gerekir.

aşağıdaki gibi tamircilik kullanarak yapabiliriz:

L:\todos> php artisan tinker

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

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

=> null

Kullanıcılar tablosunda kendimle ilgili bir sorun yaşadım.

ondan sonra gitmek için iyi

php artisan migrate:rollback

php artisan migrate

0

InnoDB veritabanı motorunu ayarla:

  Schema::create('users', function (Blueprint $table) {
            $table->engine = 'InnoDB';
            $table->increments('id');
            $table->string('name');
            $table->string('email')->unique();
            $table->string('password');
            $table->rememberToken();
            $table->timestamps();
        });

0

Diğer tüm yanıtları denediyseniz ve çalışmadıysanız, tüm komutları veritabanından bırakabilir ve daha sonra bu komutu kullanarak bir defada migrate komutunu yürütebilirsiniz:

php artisan migrate:fresh
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.