Error de migración de Laravel: Error de sintaxis o infracción de acceso: 1071 La clave especificada era demasiado larga; la longitud máxima de la clave es de 767 bytes

178

Error de migración en Laravel 5.4 con php artisan make:auth

[Illuminate \ Database \ QueryException] SQLSTATE [42000]: Error de sintaxis o infracción de acceso: 1071 La clave especificada era demasiado larga; la longitud máxima de la clave es de 767 bytes (SQL: alter tabl e usersadd unique users_email_unique( email))

[PDOException] SQLSTATE [42000]: Error de sintaxis o infracción de acceso: 1071 La clave especificada era demasiado larga; la longitud máxima de la clave es de 767 bytes

absiddiqueLive
fuente
3
Debería responder su pregunta en una respuesta. No en la pregunta. stackoverflow.com/help/self-answer
Can Vural
Gracias por la sugerencia @ can-vural, lo hice.
absiddiqueLive

Respuestas:

283

De acuerdo con la documentación oficial , puede resolver esto con bastante facilidad.

Agregue las siguientes dos líneas de código a 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 reserva siempre la cantidad máxima para un campo UTF8 que es de 4 bytes, por lo que con 255 + 255 con su CONJUNTO DE CARACTERES POR DEFECTO utf8mb4 COLLATE utf8mb4_unicode_ci; está por encima del límite de longitud máxima de la clave 767. Por @scaisedge

absiddiqueLive
fuente
3
Ten cuidado con esta solución. Si indexa campos de correo electrónico, por ejemplo, los correos electrónicos almacenados solo pueden tener una longitud máxima de 191 caracteres. Esto es menos que los estados oficiales de RFC.
shock_gone_wild
Está funcionando y es una solución válida, pero solo quería señalar que existen posibles dificultades con este enfoque.
shock_gone_wild
Espero que esta solución no llegue a morderme el culo en el futuro, pero por ahora, esto funciona. Sin embargo, tendré que tener cuidado con la forma en que indexo los correos electrónicos.
deusofnull
44
por qué exactamente 191 caracteres @absiddiqueLive
PseudoAj
121

No sé por qué la solución anterior y la solución oficial que está agregando

Schema::defaultStringLength(191);

en AppServiceProviderno funcionó para mí. Lo que funcionó fue editar el database.phparchivo en la configcarpeta. Solo edita

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

a

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

y debería funcionar, aunque no podrá almacenar caracteres multibyte extendidos como emoji .

Lo hice con Laravel 5.7. Espero eso ayude.

Koushik Das
fuente
55
El uso de este conjunto de caracteres solo le permitirá guardar ASCII estándar, y no caracteres especiales de varios bytes como los del árabe, el hebreo, la mayoría de los scripts europeos y, por supuesto, los emoji. ver también stackoverflow.com/a/15128103/4233593
Jeff Puckett el
77
Creo que te perdiste esta parte use Illuminate\Support\Facades\Schema;en la parte superior.
pimpace
@KoushikDas, ¿qué versión de Laravel estás usando?
pimpace
Ahora estoy en 6.0. Creo que lo hice inicialmente con 5.7 o 5.6 tal vez.
Koushik Das
2
La utf8mb4recopilación está ahí por una razón, recomiendo usarla si puedes.
Llama
85

Solo estoy agregando esta respuesta aquí, ya que es la quickestsolución para mí. Simplemente configure el motor de base de datos predeterminado 'InnoDB'en

/config/database.php

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

luego ejecute php artisan config:cachepara borrar y actualizar la caché de configuración

Dexter Bengil
fuente
1
Esta debería ser la respuesta / solución oficial a esta pregunta ... Gracias
Syamsoul Azrien
1
Esta es la solución real, otras son soluciones alternativas
Luís Cunha
3
pero cuál es la lógica detrás de esto
Zulfiqar Tariq
1
Esa es la solución correcta. Pero por qué no se ha incluido en la instalación predeterminada.
Ankit Chauhan
38

En el AppServiceProvider.php, incluye este código en la parte superior del archivo.

use Illuminate\Support\Facades\Schema;

public function boot()
{
Schema::defaultStringLength(191);
}
usuario7688086
fuente
Gracias me ayudó
The Dead Man
24

Este problema está causado en Laravel 5.4 por la versión de la base de datos.

Según los documentos (en la Index Lengths & MySQL / MariaDBsección):

Laravel utiliza el utf8mb4conjunto de caracteres por defecto, que incluye soporte para almacenar "emojis" en la base de datos. Si está ejecutando una versión de MySQL anterior a la versión 5.7.7 o MariaDB anterior a la versión 10.2.2, es posible que deba configurar manualmente la longitud de cadena predeterminada generada por las migraciones para que MySQL cree índices para ellos. Puede configurar esto llamando al Schema::defaultStringLengthmétodo dentro de su AppServiceProvider.

En otras palabras, en <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);
}

// ...

}

Pero como dice el comentario sobre la otra respuesta:

Ten cuidado con esta solución. Si indexa campos de correo electrónico, por ejemplo, los correos electrónicos almacenados solo pueden tener una longitud máxima de 191 caracteres. Esto es menos que los estados oficiales de RFC.

Entonces la documentación también propone otra solución:

Alternativamente, puede habilitar la innodb_large_prefixopción para su base de datos. Consulte la documentación de su base de datos para obtener instrucciones sobre cómo habilitar esta opción correctamente.

Esteban Herrera
fuente
16

Para alguien que no quiere cambiar AppServiceProvider.php. (En mi opinión, es mala idea cambiar AppServiceProvider.phpsolo por migración)

Puede volver a agregar la longitud de datos al archivo de migración database/migrations/como se muestra a continuación:

create_users_table.php

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

create_password_resets_table.php

$table->string('email',128)->index();
helloroy
fuente
Esto puede ser un problema ya que los correos electrónicos pueden tener hasta 255 caracteres (ish)
Half Crazed
Tienes razón @HalfCrazed, pero sugiero esta respuesta stackoverflow.com/questions/1297272
helloroy
mi problema fue solucionable exactamente con esta solución. Mis campos no eran correos electrónicos.
Tharaka Devinda
11

Si enfrenta este error mientras trabaja en laravel mientras usa el comando: php artisan migrate simplemente agrega 2 líneas en el archivo: app-> Providers-> AppServiceProvider.php

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

Por favor revise esta imagen . luego ejecute el php artisan migratecomando nuevamente.

Abdul Rasheed
fuente
1
es muy importante agregar 'use Schema;'. Así que esta es la mejor respuesta
hxwtch
También puede hacer esto en una línea agregando una barra diagonal '\' antes de la segunda línea como esta\Schema::defaultStringLength(191);
Tahir Afridi,
10

Estoy agregando dos soluciones que funcionan para mí.

La primera solución es :

  1. Abra el archivo database.php insde config dir / folder.
  2. Editar 'engine' => null,a'engine' => 'InnoDB',

    Esto funcionó para mí.

La segunda solución es:

  1. Abra el archivo database.php insde config dir / folder.
    2. Editar
    'charset' => 'utf8mb4', 'collation' => 'utf8mb4_unicode_ci',
    a

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


Buena suerte

Arslan Ahmad
fuente
10

actualizar e insertar estas líneas en 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
}
Anjani Barnwal
fuente
8

He resuelto este problema y edité mi archivo config-> database.php para que me guste mi base de datos ('charset' => 'utf8') y el ('collation' => 'utf8_general_ci') , por lo que mi problema está resuelto el código como seguir:

'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
fuente
8

He encontrado dos soluciones para este error.

OPCIÓN 1:

Abra su usuario y password_reset tabla de base de datos / migraciones carpeta

Y simplemente cambie la longitud del correo electrónico:

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

OPCION 2:

Abra su app/Providers/AppServiceProvider.phparchivo y dentro del boot()método establezca una longitud de cadena predeterminada:

use Illuminate\Support\Facades\Schema;

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

1- Ve /config/database.phpy encuentra estas líneas

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

y cambiarlos a:

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

2- Ejecutar php artisan config:cachepara reconfigurar laravel

3- Elimine las tablas existentes en su base de datos y luego php artisan migratevuelva a ejecutar

mohammad asghari
fuente
1
Esta es la mejor respuesta para laravel 5.8. Pero elimine las tablas ya creadas
Magige Daniel
pero de acuerdo con la documentación, ¿"utf8" usará el modo utf8 en desuso?
NoBugs
5

En el archivo AppServiceProvider.php :

 use Illuminate\Support\Facades\Schema;

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

En lugar de establecer un límite de longitud, propondría lo siguiente, que me ha funcionado.

Dentro:

config / database.php

reemplace esta línea por mysql:

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

con:

'engine' => null,
Md. Noor-A-Alam Siddique
fuente
4

Como se describe en la guía de Migraciones para solucionar esto, todo lo que tiene que hacer es editar su app/Providers/AppServiceProvider.phparchivo y, dentro del método de arranque, establecer una longitud de cadena predeterminada:

use Illuminate\Support\Facades\Schema;

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

Nota: primero tiene que eliminar (si tiene) la tabla de usuarios , la tabla de contraseña_restablecimientos de la base de datos y eliminar las entradas de usuarios y contraseña_restablecimientos de las migraciones tabla de .

Para ejecutar todas sus migraciones pendientes, ejecute el migratecomando Artisan:

php artisan migrate

Después de eso, todo debería funcionar normalmente.

Dexter Bengil
fuente
4

Como ya se especificó, agregamos a AppServiceProvider.php en App / Providers

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

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

puede ver más detalles en el siguiente enlace (busque "Longitudes de índice y MySQL / MariaDB") https://laravel.com/docs/5.5/migrations

¡PERO BIEN, eso no es lo que publiqué! El problema es que, incluso al hacer lo anterior, es probable que obtenga otro error (es decir, cuando ejecuta el php artisan migratecomando y, debido al problema de la longitud, la operación probablemente se atasque en el medio. La solución está debajo y es probable que se cree la tabla de usuario sin el resto o no del todo correctamente) necesitamos retroceder . la reversión predeterminada no funcionará. porque a la operación de migración no le gustaba terminar. necesita eliminar las nuevas tablas creadas en la base de datos manualmente.

podemos hacerlo usando tinker como se muestra a continuación:

L:\todos> php artisan tinker

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

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

=> null

Yo mismo tuve un problema con la tabla de usuarios.

después de eso eres bueno para ir

php artisan migrate:rollback

php artisan migrate

Mohamed Allal
fuente
4

La solución que nadie dice es que en Mysql v5.5 y posteriores, InnoDB es el motor de almacenamiento predeterminado que no tiene este problema, pero en muchos casos como el mío hay algunos archivos de configuración mysql ini antiguos que usan el motor de almacenamiento MYISAM antiguo como se muestra a continuación.

default-storage-engine=MYISAM

que está creando todos estos problemas y la solución es cambiar el motor de almacenamiento predeterminado a InnoDB en el archivo de configuración ini de Mysql de una vez por todas en lugar de hacer hacks temporales.

default-storage-engine=InnoDB

Y si usted está en MySQL v5.5 o posterior entonces InnoDB es el motor predeterminado por lo que no es necesario establecer de manera explícita como la de arriba, basta con retirar el default-storage-engine=MYISAMcaso de que exista de su iniarchivo y que son buenos para ir.

Ali A. Dhillon
fuente
¡Gracias! Tuve que usar esta sugerencia junto con la longitud de la cadena, el conjunto de caracteres y los cambios de clasificación para que esto funcione con laravel 6 y mysql 5.6. Esperemos que esto ayude a otros en el futuro.
Casper Wilkes
@CasperWilkes no tiene que hacer nada de esa longitud de cadena, conjunto de caracteres. Verifique su variable de sistema Mysql como esta show global variables like 'innodb_large_prefix';, debería estar ENCENDIDA . Si está APAGADO , puede verificar esta respuesta sobre cómo encenderlo. Y aquí hay más información sobre innodb_large_prefix en dev.mysql.com.
Ali A. Dhillon
3

Si desea cambiar en AppServiceProvider, debe definir la longitud del campo de correo electrónico en la migración. simplemente reemplace la primera línea de código por la segunda línea.

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

Después de los cambios exitosos, puede ejecutar la migración.
Nota: primero debe eliminar (si tiene) la tabla de usuarios , la tabla de contraseña_restablecimientos de la base de datos y eliminar las entradas de usuarios y contraseñas_contraseña de la tabla de migración.

Chintan Kotadiya
fuente
3

Schema::defaultStringLength(191);definirá la longitud de todas las cadenas 191 por defecto, lo que puede arruinar su base de datos. No debes ir por este camino.

Simplemente defina la longitud de cualquier columna específica en la clase de migración de base de datos. Por ejemplo, estoy definiendo el "nombre", "nombre de usuario" y "correo electrónico" en la CreateUsersTableclase de la siguiente manera:

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
fuente
1
Esto es lo más preferible para mí, ya que preferiría no modificar ningún código central de Laravel.
Okiemute Omuta
2

Esto es común ya que Laravel 5.4 cambió el conjunto de caracteres predeterminado de la base de datos a utf8mb4. Lo que debe hacer es: editar su App \ Providers.php poniendo este código antes de la declaración de clase

use Illuminate\Support\Facades\Schema;

Además, agregue esto a la función 'boot' Schema::defaultStringLength(191);

Tesoro
fuente
2

Si aún no tiene datos asignados a su base de datos, haga lo siguiente:

  1. Vaya a app / Providers / AppServiceProvide.php y agregue

use Illuminate \ Support \ ServiceProvider;

y dentro del método boot ();

Esquema :: defaultStringLength (191);

  1. Ahora elimine los registros en su base de datos, tabla de usuario para ej.

  2. ejecuta lo siguiente

php artisan config: caché

php artesanal migrar

Polaco Levinski
fuente
Funcionó pero la necesidad de agregar use Illuminate\Support\Facades\Schema; use Illuminate\Support\ServiceProvider;ya está allí. Espero que lo
corrijas
2

Como se describe en la guía de Migraciones para solucionar esto, todo lo que tiene que hacer es editar su archivo AppServiceProvider.php y, dentro del método de arranque, establecer una longitud de cadena predeterminada:

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

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

Espero que esto te ayude ... amigos ...

Rohit Saini
fuente
2

Acabo de modificar la siguiente línea usersypassword_resets archivo de migración.

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

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

Mahesh Gaikwad
fuente
1

Creo que forzar a StringLenght a 191 es una muy mala idea. Así que investigo para entender lo que está pasando.

Noté que este mensaje de error:

SQLSTATE [42000]: Error de sintaxis o infracción de acceso: 1071 La clave especificada era demasiado larga; la longitud máxima de la clave es de 767 bytes

Comencé a aparecer después de actualizar mi versión de MySQL. Así que revisé las tablas con PHPMyAdmin y noté que todas las tablas nuevas creadas tenían la clasificación utf8mb4_unicode_ci en lugar de utf8_unicode_ci para las antiguas.

En mi archivo de configuración de doctrina, noté que charset estaba configurado en utf8mb4, pero todas mis tablas anteriores fueron creadas en utf8, por lo que supongo que esto es una actualización de magia que comienza a funcionar en utf8mb4.

Ahora la solución fácil es cambiar el juego de caracteres de línea en su archivo de configuración ORM. Luego, suelte las tablas usando utf8mb4_unicode_ci si está en modo dev o arregle el juego de caracteres si no puede soltarlas.

Para Symfony 4

cambie charset: utf8mb4 a charset: utf8 en config / packages / doctrine.yaml

Ahora mis migraciones de doctrina están funcionando nuevamente bien.

Kaizoku Gambare
fuente
1

La solución recomendada es habilitar innodb_large_prefix opción de MySQL para que no tenga problemas posteriores. Y aquí está cómo hacer eso:

Abra el my.iniarchivo de configuración de MySQL y agregue las siguientes líneas debajo de la [mysqld]línea como esta.

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

Después de eso, guarde sus cambios y reinicie su servicio MySQL.

Retroceda si lo necesita y luego vuelva a ejecutar su migración.


En caso de que su problema persista, vaya al archivo de configuración de su base de datos y configure

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

¡Espero eso ayude!

Sammie
fuente
1

primero elimine todas las tablas de la base de datos en el host local

Cambie las propiedades de la base de datos predeterminada de Laravel (utf8mb4) en el archivo config / database.php a:

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

después de cambiar las propiedades de mi base de datos local utf8_unicode_ci. PHP artesanal migrar está bien.

Goldman.Vahdettin
fuente
0

Para cualquier otra persona que pudiera encontrarse con esto, mi problema era que estaba haciendo una columna de tipo stringe intentando hacerlo ->unsigned()cuando quise que fuera un número entero.

Brynn Bateman
fuente
0

La aproximación a ese trabajo aquí fue pasar un segundo parámetro con el nombre clave (uno corto):

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

Estaba recibiendo este error a pesar de que ya tenía (en realidad porque ya tenía) Schema :: defaultStringLength (191); en mi archivo AppServiceProvider.php.

La razón es porque estaba tratando de establecer un valor de cadena en una de mis migraciones a un valor superior a 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();
});

Eliminar el 1000 o configurarlo en 191 resolvió mi problema.

Jacey
fuente