Ошибка миграции Laravel: синтаксическая ошибка или нарушение прав доступа: 1071 Указанный ключ слишком длинный; максимальная длина ключа 767 байт

76

Ошибка миграции на Laravel 5.4 с помощью php artisan make:auth

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

[PDOException] SQLSTATE [42000]: ошибка синтаксиса или нарушение доступа: 1071 Указанный ключ был слишком длинным; максимальная длина ключа составляет 767 байт.

  • 3
    Вы должны ответить на свой вопрос в ответе. Не в этом вопросе. stackoverflow.com/help/self-answer
  • 0
    Спасибо за предложение @ can-vural, я сделал.
Теги:
laravel-5
laravel-5.4
pdo

24 ответа

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

Проблема решается следующим образом.

Добавьте следующий код в AppServiceProvider.php

L5_root/app/Providers/AppServiceProvider.php

Кодовый блок

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

function boot()
{
    Schema::defaultStringLength(191); //Solved by increasing StringLength
}

MySQL всегда резервирует максимальную сумму для поля UTF8, которое составляет 4 байта, поэтому с 255 + 255 с вашим DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; вы превысили ограничение длины ключа 767. По @scaisedge

  • 1
    Будьте осторожны с этим решением. Например, если вы индексируете поля электронной почты, хранимые электронные письма могут иметь максимальную длину 191 символа. Это меньше, чем заявляет официальный RFC.
  • 1
    Это решение предложено Laravel github.com/laravel/framework/issues/17508 laracasts.com/discuss/channels/laravel/…
Показать ещё 7 комментариев
51

Я не знаю, почему это решение и официальное решение, добавляющее

Schema::defaultStringLength(191);

in AppServiceProvider не работал у меня. Работала для редактирования файла database.php в папке config. Просто отредактируйте

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

to

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

и он должен работать. Надеюсь, что это поможет.

  • 1
    Использование этого набора символов позволит вам сохранять только стандартные ASCII, а не многобайтовые специальные символы, такие как символы из арабского языка, иврита, большинства европейских сценариев и, конечно, смайликов. см. также stackoverflow.com/a/15128103/4233593
  • 0
    Спасибо, вы действительно помогаете ..
Показать ещё 3 комментария
27

Я просто добавляю этот ответ здесь, так как это самое quickest решение для меня. Просто установите ядро базы данных по умолчанию на 'InnoDB' на

/config/database.php

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

затем запустите php artisan config:cache чтобы очистить и обновить кеш конфигурации

  • 2
    Работает отлично, спасибо.
  • 1
    смена движка с нуля на InnoDB сработала
Показать ещё 4 комментария
21

В AppServiceProvider.php вы включаете этот код вверху файла.

use Illuminate\Support\Facades\Schema;

И вы добавляете этот код в метод загрузки.

 Schema::defaultStringLength(191);
17

Эта проблема вызвана в Laravel 5.4 версией базы данных.

В соответствии с docs (в разделе Index Lengths & MySQL / MariaDB):

Laravel использует набор символов utf8mb4 по умолчанию, который включает поддержка хранения "emojis" в базе данных. Если вы используете версия MySQL старше версии 5.7.7 или MariaDB старше, чем выпуск 10.2.2, вам может потребоваться вручную настроить по умолчанию длина строки, генерируемая миграциями, чтобы 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 для своего база данных. Обратитесь к документации по базе данных для получения инструкций по как правильно включить эту опцию.

11

Для тех, кто не хочет менять 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();
  • 0
    Это может быть проблемой, поскольку электронные письма могут содержать до 255 символов.
  • 0
    Вы правы @HalfCrazed, но я предлагаю этот ответ stackoverflow.com/questions/1297272
6

Я решил эту проблему и отредактировал мой файл config-> database.php так, чтобы он соответствовал моей базе данных ('charset' => 'utf8') и ('collation' => 'utf8_general_ci'), поэтому моя проблема решена кодом следующим образом:

'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,
    ],
5

Вместо того, чтобы устанавливать ограничение по длине, я бы предложил следующее, что сработало для меня.

внутри

конфиг /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 из таблицы миграции, а затем после удаления старых таблиц запустить команду php artisan migrate

4

Как уже было указано, мы добавляем файл AppServiceProvider.php в App/Providers.

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

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

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

php artisan migrate:rollback

php artisan migrate

3

Schema::defaultStringLength(191); по умолчанию определит длину всех строк 191, что может испортить вашу базу данных. Вы не должны идти по этому пути.

Просто определите длину любого конкретного столбца в классе миграции базы данных. Например, я определяю "имя", "имя пользователя" и "электронная почта" в классе CreateUsersTable как 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.
3

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

use Illuminate\Support\Facades\Schema;

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

Примечание: сначала вы должны удалить (если есть) таблицу пользователей, таблицу password_resets из базы данных и удалить записи пользователей и password_resets из таблицы миграции.

Чтобы выполнить все оставшиеся миграции, выполните команду migrate Artisan:

php artisan migrate

После этого все должно работать как обычно.

2

обновите и вставьте эти строки в app/Providers/AppServiceProvider.php

use Illuminate\Support\Facades\Schema;  //insert this line
public function boot()
{
    Schema::defaultStringLength(191); //insert this line also
}

установите ваш движок базы данных в config/database.php в массиве "mysql"

'engine' => 'InnoDB',
2

Я добавляю два решения, которые работают для меня.

1-е растворение это :

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


Удачи

2

Это часто встречается, поскольку Laravel 5.4 изменил установленный по умолчанию характер базы данных на utf8mb4. Что вы должны сделать, это: отредактируйте ваш App\Providers.php, поместив этот код перед объявлением класса

use Illuminate\Support\Facades\Schema;

Также добавьте это в "загрузочную" функцию Schema::defaultStringLength(191);

2

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

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

После успешных изменений вы можете выполнить миграцию.
Примечание: сначала вам нужно удалить (если есть) таблица пользователей, пароль_resets table из базы данных и удалить записи пользователей и password_resets из таблицы миграции.

1

Рекомендуемое решение состоит в том, чтобы включить параметр MySQL innodb_large_prefix чтобы innodb_large_prefix последующих проблем. А вот как это сделать:

Откройте файл конфигурации my.ini MySQL и добавьте следующие строки под строкой [mysqld] следующим образом.

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

После этого сохраните изменения и перезапустите службу MySQL.

Откат, если вам нужно, а затем повторно запустите миграцию.


На случай, если проблема не устранена, перейдите в файл конфигурации базы данных и установите

'engine' => null, чтобы 'engine' => 'innodb row_format=dynamic'

Надеюсь, поможет!

1

Я только что изменил следующую строку в файле миграции users и password_resets.

Старый: $table->string('email')->unique();

Новое: $table->string('email', 128)->unique();

Вуаля !!

1

Я думаю, что заставить StringLenght на 191 действительно плохая идея. Поэтому я расследую, чтобы понять, что происходит.

Я заметил, что это сообщение об ошибке:

SQLSTATE [42000]: синтаксическая ошибка или нарушение прав доступа: 1071 Указанный ключ слишком длинный; максимальная длина ключа 767 байт

Начал появляться после того, как я обновил свою версию MySQL. Поэтому я проверил таблицы с помощью PHPMyAdmin и заметил, что все новые таблицы были созданы с сопоставлением utf8mb4_unicode_ci вместо utf8_unicode_ci для старых.

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

Теперь несложное решение состоит в том, чтобы изменить линейный набор символов в вашем конфигурационном файле ORM. Затем удалите таблицы с помощью utf8mb4_unicode_ci, если вы находитесь в режиме разработки, или исправьте кодировку, если вы не можете их удалить.

Для Symfony 4

изменить кодировку: utf8mb4 на кодировку: utf8 в config/packages/doctrine.yaml

Теперь мои доктрины миграции снова работают хорошо.

  • 0
    Спасибо, это работа для моего убунту!
1

Чтобы не менять что-либо в коде, просто обновите свой сервер MySQL до 5.7.7

Ссылка на это для получения дополнительной информации: https://laravel-news.com/laravel-5-4-key-too-long-error

0

Если вы столкнулись с этой ошибкой во время работы над laravel при использовании команды: "php artisan migrate", то вы просто добавляете в файл 2 строки: app-> Providers-> AppServiceProvider.php

  1. использовать схему;
  2. Схема :: defaultStringLength (191);

пожалуйста, проверьте изображение. затем снова запустите команду "php artisan migrate". php ремесленник мигрировать

0

Подходящие к этой работе здесь передают второй параметр с ключевым именем (коротким):

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

Для всех, кто мог столкнуться с этим, моя проблема заключалась в том, что я делал столбец типа string и пытался сделать его ->unsigned() когда я хотел, чтобы он был целым числом.

-2

Для меня, что работало, чтобы обновить зависимости, запустив.

composer update

Вам также следует установить последнюю версию mysql.

Ещё вопросы

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