Миграция Laravel: уникальный ключ слишком длинный, даже если указан

131

Я пытаюсь перенести таблицу пользователей в Laravel. Когда я запускаю миграцию, я получаю эту ошибку:

[Illuminate\Database\QueryException] SQLSTATE [42000]: Синтаксическая ошибка или нарушение доступа: 1071 Указанный ключ был слишком длинным; максимальная длина ключа составляет 767 байт (SQL: alter table users добавить уникальный users_email_uniq (email))

моя миграция выглядит следующим образом:

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');
});

После некоторого googling я встретил этот отчет об ошибках, где Тейлор говорит, что вы можете указать индексный ключ как второй параметр unique(), который я сделал. Он все еще дает ошибку. Что здесь происходит?

  • 0
    Почему вы используете 320 символов для электронной почты? Это может быть вашей проблемой.
  • 1
    Это была действительно проблема, не знаю почему. Но да, вы правы, я не знаю, почему я указал длину символа для каждого поля. Сняли эти ограничения
Показать ещё 4 комментария
Теги:

33 ответа

218
Лучший ответ

Укажите меньшую длину для вашего электронного письма:

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

Это значение по умолчанию:

$table->string('email');

И ты должен быть хорошим.

Для Laravel 5.4 вы можете найти решение в этом Laravel 5.4: Указанный ключ был слишком длинной ошибкой, сообщение Laravel News:

Как указано в Руководстве по миграции, чтобы исправить это все, что вам нужно сделать, это отредактировать файл AppServiceProvider.php и внутри метода загрузки установить длину строки по умолчанию:

use Illuminate\Support\Facades\Schema;

public function boot()
{
    Schema::defaultStringLength(191);
}
  • 4
    Максимально возможная длина электронной почты составляет 254 поэтому, вероятно, стоит помнить об этом, поэтому я бы, вероятно, проверил уникальность, используя валидатор в этом случае.
  • 0
    Я думаю, что оценка выиграла, потому что она безопаснее, так как она действительно реализует кодировку в базе данных, вместо того, чтобы делать трюки, вы, вероятно, найдете проблемы с смайликами.
Показать ещё 4 комментария
90

Обновление 1

В Laravel 5.4 эти изменения больше не нужны.

Laravel 5.4 использует по умолчанию набор символов utf8mb4, который включает в себя поддержку для хранения "emojis" в базе данных. Если вы обновляете свое приложение из Laravel 5.3, вам не требуется переключаться на этот набор символов.

Обновление 2

Текущее исполнение версий MariaDB НЕ поддерживает этот параметр по умолчанию по всему миру. Он реализован в MariaDB 10.2.2+ по умолчанию.

Решение

И если вы намеренно хотите использовать правильное будущее-умолчанию (начиная с Laravel 5.4), многобайтовая поддержка UTF8 utf8mb4 для , тогда начните исправление вашей конфигурации базы данных.

В Laravel config/database.php define:

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

DYNAMIC позволяет хранить индексы long key.

Настройки сервера (по умолчанию включены в MySQL 5.7.7+/MariaDB 10.2.2 +):

[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

Для клиентов:

[mysql]
default-character-set=utf8mb4

И затем STOP ваш сервер MySQL/MariaDB. После этого СНВ. Горячий RESTART может не работать.

sudo systemctl stop mysqld
sudo systemctl start mysqld

Теперь у вас есть Laravel 5.x с поддержкой UTF8.

  • 3
    Это может хорошо работать с MySQL 5.5 (не пытался перенастроить). 5.7 (вероятно, также 5.6) работал без необходимости перенастройки. 5.7 был дистрибутивом Сервера совместной работы по умолчанию с ванильной конфигурацией.
  • 0
    Я изменил движок в моем database.php, как вы упомянули, но он все еще создает таблицы с row = compact, что вызывает проблему. Я не совсем понял, вы говорите, что недостаточно внести это изменение в database.php и что также необходимо внести изменения в файл my.cnf?
Показать ещё 4 комментария
43

Если вы включены или обновлены в Laravel 5.4, это сработало для меня;

Всего 1 изменение. в AppServiceProvider.php

use Illuminate\Support\Facades\Schema;

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

Как упоминалось в руководстве по миграции https://laravel.com/docs/master/migrations#creating-indexes

  • 0
    Я сделал это на самой миграции.
  • 4
    Это (предположительно), потому что каждый символ занимает ровно 4 байта, а максимальная длина ключа измеряется в байтах, а не в символах. Таким образом, длина ключа будет на 191 * 4 = 764 байта, просто smidgen под максимальными 767 байтами, которые будет поддерживать база данных. Решения нуждаются в объяснениях IMO, если они хотят внести свой вклад в обмен знаниями здесь, а не просто предоставить «процедуры». Но удобное решение тем не менее.
32

Если кто-то еще наткнется на этот ответ, как я, но по другой причине, вы можете проверить свою кодировку/сортировку DB Laravel.

Я устанавливал приложение (Snipe-IT) и настраивал конфигурацию базы данных Laravel для использования следующего:

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

Удаление mb4 из обеих строк исправило проблему, хотя я считаю, что ответ Антонио - это реальное решение проблемы.

18

Это сработало для меня:

 $table->charset = 'utf8';
 $table->collation = 'utf8_unicode_ci';
  • 0
    Это сработало для меня. Я использую версию сервера: 10.1.22-MariaDB - Источник распространения
  • 0
    Я тоже работал. Я использую версию Laravel: 5.6
Показать ещё 1 комментарий
13

Удалите mb4 из charset и сортировки из config/database.php, затем он будет успешно выполнен.
'charset' = > 'utf8',
'collation' = > 'utf8_unicode_ci',

11

Для laravel 5.4 просто отредактируйте файл

App\Providers\AppServiceProvider.php

use Illuminate\Support\Facades\Schema;

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

Я столкнулся с той же проблемой и исправил ее, добавив две строки в мое приложение /database.php

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

Мой файл выглядит следующим образом:

<?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',

    ......
  • 0
    Если вы установили новую версию в Laravel. Пожалуйста, удалите 'mb4' из utf8mb4 & utf8mb4_unicode_ci & config / database.php
9

Для Laravel 5,6
Это решение решит мою проблему
перейдите в 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' => 'utf8mb4',
    'collation' => 'utf8mb4_unicode_ci',
    'prefix' => '',
    'strict' => true,
    'engine' => null,
],

Изменить это два поля

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

С этим

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

TO ->
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
  • 1
    Хотя это может ответить на вопрос, лучше добавить описание того, как этот ответ может помочь решить проблему. Пожалуйста, прочитайте Как я могу написать хороший ответ, чтобы узнать больше.
5

В файле config/database.php где:

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

Измените эту строку следующим образом:

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

Я добавил к самой миграции

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

да, я знаю, что мне нужно учитывать это при каждой миграции, но я предпочел бы, чтобы это было спрятано у какого-то совершенно несвязанного поставщика услуг

3

для laravel 5.7 напишите этот код в appserviceprovider.php

  use Illuminate\Support\Facades\Schema;

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

У меня была та же проблема, и я использую wamp

Решение: Открыть файл: конфигурации /database.php

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

Спасибо

  • 0
    Ни один из предыдущих ответов не сработал для меня, но этот сработал как шарм! И это имеет смысл, я считаю, что в предыдущих версиях движка Laravel DB по умолчанию был установлен InnoDB, поэтому мы не сталкивались с этими ошибками ранее.
  • 0
    да нужно было сделать пару других ответов и это тоже.
2

Если у кого-то возникла эта проблема даже после выполнения вышеуказанных изменений. Для примера, в моем случае я сделал ниже изменения,

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

Но это не сработает сразу по двум причинам. Во-первых, если вы используете lumen вместо laravel, вам, возможно, придется сначала раскомментировать эту строку в файле app.php.

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

А затем вам нужно снова создать сценарий миграции с помощью команды ремесленника,

php artisan make:migration <your_table_name>

Поскольку теперь будут работать только те изменения, которые вы внесли в ServiceProvider.

2

Для пользователей Laravel> = 5.6

Откройте файл AppServiceProvider.php

Используйте следующий класс

use Illuminate\Support\Facades\Schema;

Затем внутри метода boot добавьте следующую строку

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

Если вы на или обновлены до версии Laravel 5.4 и последней версии, она работает.
Всего 1 изменение в AppServiceProvider.php

use Illuminate\Support\Facades\Schema;

public function boot()
{
  Schema::defaultStringLength(191);
}
  • 0
    Это также работает для меня для Laravel 5.5
2

Это потому, что Laravel 5.4 использует utf8mb4, который поддерживает сохранение emojis.

Добавьте это в свое приложение\Провайдеры\AppServiceProvider.php

use Illuminate\Support\Facades\Schema;

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

и вам должно быть хорошо идти.

1

У меня возникла проблема, измените конфигурацию "config/database"

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

сохраняя тот же шаблон в базе данных.

Затем я дал команду

php artisan migrate
1

Я хотел бы указать на то, что я пропустил...

Я новичок в Laravel, и я не скопировал "использовать Illuminate.....", потому что я действительно не обращал внимания, потому что прямо над загрузкой функции, которую вы уже прочитали, есть оператор использования.

Надеюсь, это поможет кому-нибудь

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

public function boot()
{
    Schema::defaultStringLength(191);
}
  • 0
    Вы также можете просто добавить любой Фасад с префиксом \
1

Laravel использует набор символов utf8mb4 по умолчанию, который включает в себя поддержку для хранения "emojis" в базе данных. Если вы используете версию MySQL старше версии 5.7.7 или MariaDB старше версии 10.2.2, вам может потребоваться вручную настроить длину строки по умолчанию, сгенерированную миграциями, чтобы MySQL создавал для них индексы. Вы можете настроить это, вызвав метод Schema::defaultStringLength в своем AppServiceProvider:

use Illuminate\Support\Facades\Schema;

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

Вы можете проверить

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

  • 0
    спасибо, у меня работает. mamp mysql с laravel 5.6.23
1

Измените charset на 'utf8mb4' на 'utf8' и

сопоставление с 'utf8mb4_unicode_ci' в 'utf8_unicode_ci'

в файле config/database.php

Это сработало для меня.

0

Укажите меньшую длину строки электронной почты, например:

$table->string('email',128)->unique(); //In create user table

А также

$table->string('email',128)->index(); // create password resets table

Это определенно будет работать.

  • 0
    Чем это отличается от принятого ответа?
0

РЕШЕНИЕ:

Сначала измените defaultStringLength на 191 в app\Providers\AppServiceProvider.php:

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

Затем измените значения набора символов и параметров сортировки следующим образом в config\database.php:

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

(ссылка, чтобы узнать о MariaDB charset)

0

24 октября 2016 года Тейлор Отвелл, автор Laravel, объявил в Твиттере

"utf8mb4" будет набором символов MySQL по умолчанию в Laravel 5.4 для лучшей поддержки смайликов. Twitter Taylor Otwell Twitter Post

который до версии 5.4 набор символов был utf8

В течение этого столетия многие веб-приложения, включая чат или какую-то другую платформу, позволяли пользователям общаться, и многим людям нравится использовать смайлики или смайлики. и это своего рода супер-символы, которые требуют больше места для хранения, и это возможно только с использованием utf8mb4 в качестве кодировки. Вот почему они мигрируют в utf8mb4 только для космических целей.

если вы посмотрите в классе Illuminate\Database\Schema\Builder то увидите, что для $defaultStringLength установлено значение 255, и для его изменения вы можете пройти через фасад Schema вызвать метод defaultStringLength и передать новую длину.

чтобы выполнить это изменение, вызовите этот метод в вашем классе AppServiceProvider который находится в подкаталоге app\provider, например:

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 в качестве значения только потому, что MySQL поддерживает 767 байт, а также потому, что 767/4 есть число байтов, которое занимает каждый многобайтовый символ, вы получите 191.

Вы можете узнать больше здесь Ограничения набора символов utf8mb4 (4-байтовое кодирование Unicode UTF-8) для числа столбцов таблицы и размера строки

  • 0
    Это единственный ответ, который объясняет магическое число 191 .
0

Пожалуйста, откройте остальные файлы user и password. файлы находятся в папке базы данных/миграции.

добавить строку

Schema::defaultStringLength(191); in up function in both files.

Тогда беги

php artisan migrate
  • 0
    Это необходимо для ЛЮБОЙ модели, которая использует тип данных String, так что это не оптимально. Другие ответы имеют дело с этим один раз для ВСЕХ миграций. «Реальное / лучшее» решение зависит от вашей среды и потребностей. Если вы ДОЛЖНЫ использовать более старый MySQL (или Maria), но хотите сохранить длину 250 строк и не нуждаетесь в смайликах, переключите кодировку БД. В противном случае сократите максимальную длину строки в поставщике.
0

Если вы видите эту ошибку, то, безусловно, вам нужно внести следующие изменения в файл AppServiceProvider.php ->, который можно найти внутри app->providers:

изменения должны быть сделаны

use Illuminate\Support\Facades\Schema; //see if you have this class if not add it.

public function boot()
{
    Schema::defaultStringLength(191); //make sure you add this line
}

это должно решить вашу проблему, чтобы больше вы могли видеть новости Laravel относительно этой проблемы. https://laravel-news.com/laravel-5-4-key-too-long-error

0

Если вы попробовали все остальные ответы, но они не сработали, вы можете удалить все таблицы из базы данных, а затем сразу выполнить команду migrate, используя эту команду:

php artisan migrate:fresh
0

Установить движок базы данных InnoDB:

  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

Все было хорошо описано в других Anwser, более подробную информацию вы можете увидеть в ссылке ниже (поиск по ключу "Длина индекса и MySQL/MariaDB") https://laravel.com/docs/5.5/migrations

НО ХОРОШО, ЧЕМ НЕ О ЧЕМ ЭТО ОТВЕТ! дело даже в том, что, выполнив вышесказанное, вы захотите получить еще одну ошибку (когда вам нравится команда запуска php artisan migrate и из-за проблемы длины, операция как застрявшая посередине. решение ниже, а пользовательская таблица как созданный без остального или не совсем правильно) нам нужно бросить bac k. откат по умолчанию не подойдет. потому что операция миграции не понравилась. Вам необходимо удалить новые созданные таблицы в базе данных вручную.

мы можем сделать это с помощью повозки, как показано ниже:

L:\todos> php artisan tinker

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

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

=> null

У меня самого была проблема с таблицей пользователей.

после этого ты можешь идти

php artisan migrate:rollback

php artisan migrate
0

включить эту строку сверху

use Illuminate\Support\Facades\Schema;

затем внутри функции загрузки добавить это

public function boot()
{
    Schema::defaultStringLenght(191);
}
  • 1
    Не могли бы вы отформатировать код, выделив его и нажав Ctrl + K
0

Просто установлен MariaDB 10.2.4 RC, запускается новый пустой проект Laravel 5.4 и по умолчанию (столбцы varchar (255)).

Не нужно изменять DB conf и Laravael config/database.php. Таким образом, как @scorer отметил поведение по умолчанию для 10.2.2 +.

0

У вас не будет этой проблемы, если вы используете MySQL 5.7.7+ или MariaDB 10.2.2 +.

Чтобы обновить MariaDB на вашем Mac, используя Brew, сначала отмените текущий: brew unlink mariadb, а затем установите dev с помощью brew install mariadb --devel

После завершения установки остановить/запустить запущенную службу: brew services stop mariadb brew services start mariadb

Текущая версия для разработчиков - 10.2.3. После завершения установки вам больше не придется об этом беспокоиться, и вы можете использовать utf8mb4 (теперь это значение по умолчанию в Laravel 5.4), не возвращаясь к utf8 и не редактируя AppServiceProvider, как это предлагается в документации Laravel: https://laravel.com/docs/master/releases#laravel-5.4 (прокрутите вниз до: Миграция длины строки по умолчанию)

Ещё вопросы

Сообщество Overcoder
Наверх
Меню