Erreur de migration Laravel: erreur de syntaxe ou violation d'accès: 1071 La clé spécifiée était trop longue; la longueur maximale de la clé est de 767 octets

178

Erreur de migration sur Laravel 5.4 avec php artisan make:auth

[Illuminate \ Database \ QueryException] SQLSTATE [42000]: Erreur de syntaxe ou violation d'accès: 1071 La clé spécifiée était trop longue; la longueur maximale de la clé est de 767 octets (SQL: alter table usersadd unique users_email_unique( email))

[PDOException] SQLSTATE [42000]: Erreur de syntaxe ou violation d'accès: 1071 La clé spécifiée était trop longue; la longueur maximale de la clé est de 767 octets

absiddiqueLive
la source
3
Vous devez répondre à votre question par une réponse. Pas dans la question. stackoverflow.com/help/self-answer
Can Vural
Merci pour la suggestion @ can-vural, je l'ai fait.
absiddiqueLive le

Réponses:

283

Selon la documentation officielle , vous pouvez résoudre ce problème assez facilement.

Ajoutez les deux lignes de code suivantes à 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 réserve toujours le montant maximum pour un champ UTF8 qui est de 4 octets donc avec 255 + 255 avec votre DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; vous avez dépassé la limite de longueur de clé maximale de 767. Par @scaisedge

absiddiqueLive
la source
3
Faites attention à cette solution. Si vous indexez les champs d'e-mail par exemple, les e-mails stockés ne peuvent avoir qu'une longueur maximale de 191 caractères. C'est moins que les états officiels de la RFC.
shock_gone_wild
Cela fonctionne et c'est une solution valable, mais je voulais juste souligner qu'il y a des pièges possibles en utilisant cette approche.
shock_gone_wild
J'espère que cette solution ne viendra pas me mordre dans le cul à l'avenir, mais pour l'instant, cela fonctionne. Je devrai cependant faire attention à la façon dont j'indexe les e-mails.
deusofnull
4
pourquoi exactement 191 caractères @absiddiqueLive
PseudoAj
121

Je ne sais pas pourquoi la solution ci-dessus et la solution officielle qui ajoute

Schema::defaultStringLength(191);

en AppServiceProvidern'a pas fonctionné pour moi. Ce qui fonctionnait, c'était l'édition du database.phpfichier dans le configdossier. Modifiez simplement

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

à

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

et cela devrait fonctionner, même si vous ne pourrez pas stocker de caractères multi-octets étendus comme les emoji .

Je l'ai fait avec Laravel 5.7. J'espère que ça aide.

Koushik Das
la source
5
L'utilisation de ce jeu de caractères ne vous permettra d'enregistrer que l'ASCII standard, et non les caractères spéciaux multi-octets comme ceux de l'arabe, de l'hébreu, de la plupart des scripts européens et bien sûr des emoji. voir aussi stackoverflow.com/a/15128103/4233593
Jeff Puckett
7
Je pense que vous avez manqué cette partie use Illuminate\Support\Facades\Schema;au sommet.
pimpace
@KoushikDas quelle version de Laravel utilisez-vous?
pimpace
Maintenant, je suis sur 6.0. Je pense que je l'ai fait au départ avec 5,7 ou 5,6 peut-être.
Koushik Das
2
Le utf8mb4classement est là pour une raison, je recommande de l'utiliser si vous le pouvez.
Flamme le
85

J'ajoute simplement cette réponse ici car c'est la quickestsolution pour moi. Réglez simplement le moteur de base de données par défaut 'InnoDB'sur on

/config/database.php

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

puis exécutez php artisan config:cachepour effacer et actualiser le cache de configuration

Dexter Bengil
la source
1
Cela devrait être la réponse / solution officielle à cette question ... Merci
Syamsoul Azrien
1
C'est la solution réelle, d'autres sont des solutions de contournement
Luís Cunha
3
mais quelle est la logique derrière cela
Zulfiqar Tariq
1
C'est la bonne solution. Mais pourquoi pas, il a été inclus dans l'installation par défaut.
Ankit Chauhan le
38

Dans le AppServiceProvider.php, vous incluez ce code en haut du fichier.

use Illuminate\Support\Facades\Schema;

public function boot()
{
Schema::defaultStringLength(191);
}
user7688086
la source
Merci m'a aidé
The Dead Man
24

Ce problème est causé dans Laravel 5.4 par la version de la base de données.

Selon la documentation (dans la Index Lengths & MySQL / MariaDBsection):

Laravel utilise le utf8mb4jeu de caractères par défaut, qui inclut la prise en charge du stockage des "emojis" dans la base de données. Si vous exécutez une version de MySQL antérieure à la version 5.7.7 ou MariaDB antérieure à la version 10.2.2, vous devrez peut-être configurer manuellement la longueur de chaîne par défaut générée par les migrations afin que MySQL crée des index pour eux. Vous pouvez configurer cela en appelant la Schema::defaultStringLengthméthode dans votre AppServiceProvider.

En d'autres termes, 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);
}

// ...

}

Mais comme le dit le commentaire sur l'autre réponse:

Faites attention à cette solution. Si vous indexez les champs d'e-mail, par exemple, les e-mails stockés ne peuvent avoir qu'une longueur maximale de 191 caractères. C'est moins que les états officiels de la RFC.

La documentation propose donc également une autre solution:

Vous pouvez également activer l' innodb_large_prefixoption pour votre base de données. Reportez-vous à la documentation de votre base de données pour savoir comment activer correctement cette option.

Esteban Herrera
la source
16

Pour quelqu'un qui ne veut pas changer AppServiceProvider.php. (À mon avis, c'est une mauvaise idée de changer AppServiceProvider.phpjuste pour la migration)

Vous pouvez rajouter la longueur des données au fichier de migration database/migrations/comme ci-dessous:

create_users_table.php

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

create_password_resets_table.php

$table->string('email',128)->index();
helloroy
la source
Cela peut être un problème car les e-mails peuvent contenir jusqu'à 255 caractères (ish)
Half Crazed
Vous avez raison @HalfCrazed, mais je suggère cette réponse stackoverflow.com/questions/1297272
helloroy
mon problème était exactement résolu par cette solution. Mes champs n'étaient pas des e-mails.
Tharaka Devinda
11

Si vous rencontrez cette erreur pendant que vous travaillez sur laravel en utilisant la commande: php artisan migrate alors vous ajoutez simplement 2 lignes dans le fichier: app-> Providers-> AppServiceProvider.php

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

veuillez vérifier cette image . puis exécutez à php artisan migratenouveau la commande.

Abdul Rasheed
la source
1
il est très important d'ajouter 'use Schema;'. C'est donc la meilleure réponse
hxwtch
Vous pouvez également le faire en une ligne en ajoutant une barre oblique inversée '\' avant la deuxième ligne comme ceci\Schema::defaultStringLength(191);
Tahir Afridi
10

J'ajoute deux solutions qui fonctionnent pour moi.

La 1ère sollution est :

  1. Ouvrez le fichier database.php insde config dir / dossier.
  2. Éditer 'engine' => null, vers'engine' => 'InnoDB',

    Cela a fonctionné pour moi.

La 2ème sollution est:

  1. Ouvrez database.php fichier insde config dir / dossier.
    2. Modifier
    'charset' => 'utf8mb4', 'collation' => 'utf8mb4_unicode_ci',
    en

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


Bonne chance

Arslan Ahmad
la source
10

mettre à jour et insérer ces lignes dans 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
la source
8

J'ai résolu ce problème et modifié mon fichier config-> database.php pour aimer ma base de données ('charset' => 'utf8') et le ('collation' => 'utf8_general_ci') , donc mon problème est résolu le code comme suivre:

'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
la source
8

J'ai trouvé deux solutions à cette erreur

OPTION 1:

Ouvrez votre table user et password_reset dans le dossier database / migrations

Et changez simplement la longueur de l'e-mail:

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

OPTION 2:

Ouvrez votre app/Providers/AppServiceProvider.phpfichier et à l'intérieur de la boot()méthode définissez une longueur de chaîne par défaut:

use Illuminate\Support\Facades\Schema;

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

1- Allez /config/database.phpet trouvez ces lignes

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

et changez-les en:

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

2- Courirphp artisan config:cache pour reconfigurer laravel

3- Supprimer les tables existantes dans votre base de données, puis exécutez à php artisan migratenouveau

mohammad asghari
la source
1
c'est la meilleure réponse pour laravel 5.8. Mais supprimer les tables déjà créées
Magige Daniel
mais selon la documentation "utf8" utilisera le mode utf8 obsolète?
NoBugs
5

Dans le fichier AppServiceProvider.php :

 use Illuminate\Support\Facades\Schema;

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

Au lieu de fixer une limite de longueur, je proposerais ce qui suit, qui a fonctionné pour moi.

À l'intérieur:

config / database.php

remplacez cette ligne pour mysql:

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

avec:

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

Comme indiqué dans le guide Migrations pour résoudre ce problème, tout ce que vous avez à faire est de modifier votre app/Providers/AppServiceProvider.phpfichier et, dans la méthode de démarrage, définissez une longueur de chaîne par défaut:

use Illuminate\Support\Facades\Schema;

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

Remarque: vous devez d'abord supprimer (si vous en avez) la table users, la table password_resets de la base de données et supprimer les entrées users et password_resets des migrations table des .

Pour exécuter toutes vos migrations en cours, exécutez la migratecommande Artisan:

php artisan migrate

Après cela, tout devrait fonctionner normalement.

Dexter Bengil
la source
4

Comme déjà spécifié, nous ajoutons à AppServiceProvider.php dans App / Providers

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

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

vous pouvez voir plus de détails dans le lien ci-dessous (recherchez "Index Lengths & MySQL / MariaDB") https://laravel.com/docs/5.5/migrations

MAIS BIEN, ce n'est pas ce que j'ai publié! le problème est que même en faisant ce qui précède, vous obtiendrez probablement une autre erreur (c'est lorsque vous exécutez la php artisan migratecommande et en raison du problème de longueur, l'opération sera probablement bloquée au milieu. La solution est ci-dessous , et la table utilisateur est probablement créée sans le reste ou pas totalement correctement) nous devons reculer . la restauration par défaut ne fonctionnera pas. car l'opération de migration n'aimait pas la finition. vous devez supprimer manuellement les nouvelles tables créées dans la base de données.

nous pouvons le faire en utilisant bricoler comme ci-dessous:

L:\todos> php artisan tinker

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

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

=> null

J'ai moi-même eu un problème avec la table des utilisateurs.

après ça tu es prêt à partir

php artisan migrate:rollback

php artisan migrate

Mohamed Allal
la source
4

La solution que personne ne dit est que dans Mysql v5.5 et versions ultérieures, InnoDB est le moteur de stockage par défaut qui n'a pas ce problème, mais dans de nombreux cas, comme le mien, il existe d'anciens fichiers de configuration mysql ini qui utilisent l'ancien moteur de stockage MYISAM comme ci-dessous.

default-storage-engine=MYISAM

ce qui crée tous ces problèmes et la solution est de changer une fois pour toutes le moteur de stockage par défaut en InnoDB dans le fichier de configuration ini de Mysql au lieu de faire des hacks temporaires.

default-storage-engine=InnoDB

Et si vous êtes sur MySql v5.5 ou version ultérieure, InnoDB est le moteur par défaut, vous n'avez donc pas besoin de le définir explicitement comme ci-dessus, supprimez simplement le default-storage-engine=MYISAMs'il existe de votre inifichier et vous êtes prêt à partir.

Ali A. Dhillon
la source
Merci! J'ai dû utiliser cette suggestion en conjonction avec la longueur de la chaîne, le jeu de caractères et les changements de classement pour que cela fonctionne avec laravel 6 et mysql 5.6. J'espère que cela aidera les autres à l'avenir.
Casper Wilkes
@CasperWilkes vous n'avez rien à faire de cette longueur de chaîne, des trucs charset. Vérifiez votre variable système Mysql comme ceci, show global variables like 'innodb_large_prefix';elle devrait être activée . S'il est désactivé, vous pouvez vérifier cette réponse pour savoir comment l'activer. Et voici plus d'informations sur innodb_large_prefix sur dev.mysql.com.
Ali A. Dhillon
3

Si vous souhaitez modifier AppServiceProvider, vous devez définir la longueur du champ d'e-mail lors de la migration. remplacez simplement la première ligne de code par la deuxième ligne.

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

Une fois les modifications effectuées, vous pouvez exécuter la migration.
Remarque: vous devez d'abord supprimer (si vous avez) table d'utilisateurs , table password_resets de la base de données et d' utilisateurs supprimer et password_resets entrées de la table de migration.

Chintan Kotadiya
la source
3

Schema::defaultStringLength(191);définira la longueur de toutes les chaînes 191 par défaut, ce qui peut ruiner votre base de données. Vous ne devez pas suivre cette voie.

Définissez simplement la longueur d'une colonne spécifique dans la classe de migration de base de données. Par exemple, je définis le "nom", "username" et "email" dans la CreateUsersTableclasse comme ci-dessous:

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
la source
1
Ceci est préférable pour moi car je préfère ne pas modifier les codes de base de Laravel.
Okiemute Omuta
2

Ceci est courant depuis que Laravel 5.4 a changé le jeu de caractères de base de données par défaut en utf8mb4. Ce que vous devez faire, c'est: éditer votre App \ Providers.php en mettant ce code avant la déclaration de classe

use Illuminate\Support\Facades\Schema;

Ajoutez également ceci à la fonction 'boot' Schema::defaultStringLength(191);

Trésor
la source
2

Si aucune donnée n'est déjà affectée à votre base de données, procédez comme suit:

  1. Accédez à app / Providers / AppServiceProvide.php et ajoutez

utilisez Illuminate \ Support \ ServiceProvider;

et à l'intérieur de la méthode boot ();

Schema :: defaultStringLength (191);

  1. Supprimez maintenant les enregistrements de votre base de données, table utilisateur par exemple.

  2. exécuter ce qui suit

config artisan php: cache

php artisan migrer

Levinski polonais
la source
Cela a fonctionné mais il faut ajouter use Illuminate\Support\Facades\Schema; use Illuminate\Support\ServiceProvider;est déjà là. J'espère que vous le corrigez
Jimish Gamit
2

Comme indiqué dans le guide Migrations pour résoudre ce problème, tout ce que vous avez à faire est de modifier votre fichier AppServiceProvider.php et, dans la méthode de démarrage, définissez une longueur de chaîne par défaut:

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

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

J'espère que cela vous aidera ...

Rohit Saini
la source
2

Je viens de modifier la ligne suivante userset le password_resetsfichier de migration.

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

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

Mahesh Gaikwad
la source
1

Afin d' éviter de changer quoi que ce soit dans votre code , mettez simplement à jour votre serveur MySQL à au moins 5.7.7

Référencez-le pour plus d'informations: https://laravel-news.com/laravel-5-4-key-too-long-error

FE Noel Nfebe
la source
Non, le Mariadb 10.1.41 dans 18.04 a également cette erreur.
NoBugs
1

Je pense que forcer StringLenght à 191 est une très mauvaise idée. Alors j'enquête pour comprendre ce qui se passe.

J'ai remarqué que cette erreur de message:

SQLSTATE [42000]: Erreur de syntaxe ou violation d'accès: 1071 La clé spécifiée était trop longue; la longueur maximale de la clé est de 767 octets

J'ai commencé à apparaître après avoir mis à jour ma version de MySQL. J'ai donc vérifié les tables avec PHPMyAdmin et j'ai remarqué que toutes les nouvelles tables créées étaient avec la collation utf8mb4_unicode_ci au lieu de utf8_unicode_ci pour les anciennes.

Dans mon fichier de configuration de doctrine, j'ai remarqué que charset était défini sur utf8mb4, mais toutes mes tables précédentes ont été créées dans utf8, donc je suppose que c'est une magie de mise à jour qui commence à fonctionner sur utf8mb4.

La solution la plus simple consiste maintenant à modifier le jeu de caractères de ligne dans votre fichier de configuration ORM. Ensuite, supprimez les tables en utilisant utf8mb4_unicode_ci si vous êtes en mode dev ou corrigez le jeu de caractères si vous ne pouvez pas les supprimer.

Pour Symfony 4

changez charset: utf8mb4 en charset: utf8 dans config / packages / doctrine.yaml

Maintenant, mes migrations de doctrine fonctionnent à nouveau très bien.

Kaizoku Gambare
la source
1

La solution recommandée est d'activer l' innodb_large_prefixoption MySQL pour ne pas avoir de problèmes ultérieurs. Et voici comment faire cela:

Ouvrez le my.inifichier de configuration MySQL et ajoutez les lignes ci-dessous sous la [mysqld]ligne comme ceci.

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

Après cela, enregistrez vos modifications et redémarrez votre service MySQL.

Annulez si vous en avez besoin, puis réexécutez votre migration.


Au cas où votre problème persiste, accédez au fichier de configuration de votre base de données et définissez

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

J'espère que ça aide!

Sammie
la source
1

supprimez d'abord toutes les tables de la base de données dans l'hôte local

Modifiez les propriétés de la base de données par défaut de Laravel (utf8mb4) dans le fichier config / database.php en:

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

après avoir changé les propriétés de ma base de données locale utf8_unicode_ci. php artisan migrer c'est ok.

Goldman.Vahdettin
la source
0

Pour tous ceux qui pourraient rencontrer cela, mon problème était que je créais une colonne de type stringet que j'essayais de la créer ->unsigned()alors que je voulais que ce soit un entier.

Brynn Bateman
la source
0

L'approche qui fonctionne ici était de passer un deuxième paramètre avec le nom de la clé (un court):

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

J'obtenais cette erreur même si j'avais déjà (en fait parce que j'avais déjà) Schema :: defaultStringLength (191); dans mon fichier AppServiceProvider.php.

La raison en est que j'essayais de définir une valeur de chaîne dans l'une de mes migrations sur une valeur supérieure à 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();
});

La suppression du 1000 ou le réglage sur 191 a résolu mon problème.

Jacey
la source