web-dev-qa-db-fra.com

Migration Laravel: la clé unique est trop longue, même si elle est spécifiée

J'essaie de migrer une table d'utilisateurs à Laravel. Lorsque je lance ma migration, j'obtiens cette erreur:

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

ma migration est la suivante:

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

Après quelques recherches sur Google, je suis tombé sur ce rapport de bogue où Taylor indique que vous pouvez spécifier la clé d'index en tant que deuxième paramètre de unique(), ce que j'ai fait. Cela donne toujours l'erreur. Qu'est-ce qui se passe ici?

127
harryg

Spécifiez une longueur inférieure pour votre e-mail:

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

Quel est le défaut, en fait:

$table->string('email');

Et tu devrais être bon.

Pour Laravel 5.4, vous pouvez trouver une solution dans ceci Laravel 5.4: Erreur spécifiée: erreur trop longue, Laravel News post:

Comme indiqué dans le guide des migrations pour résoudre ce problème, il vous suffit de modifier votre fichier AppServiceProvider.php 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);
}
224

Mise à jour 1

A partir de Laravel 5.4 ces changements ne sont plus nécessaires.

Laravel 5.4 utilise par défaut le jeu de caractères utf8mb4, qui inclut la prise en charge du stockage des "emojis" dans la base de données. Si vous mettez à niveau votre application à partir de Laravel 5.3, vous n'êtes pas obligé de passer à ce jeu de caractères.

Mise à jour 2

Les versions actuelles de MariaDB en production NE PAS prennent en charge ce paramètre par défaut globalement. Il est implémenté dans MariaDB 10.2.2+ par défaut .

Solution

Et si vous souhaitez utiliser intentionnellement le support futur par défaut correct (à partir de Laravel 5.4), le support UTF8 à plusieurs octets utf8mb4 pour ???? puis commence à réparer ???? votre configuration de base de données.

Dans Laravel config/database.php, définissez:

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

DYNAMIC permet de stocker long key indexes.

Paramètres du serveur (inclus par défaut dans 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

Pour les clients:

[mysql]
default-character-set=utf8mb4

Et puis ARRÊTEZ votre serveur MySQL/MariaDB. Après que START. Le redémarrage à chaud peut ne pas fonctionner.

Sudo systemctl stop mysqld
Sudo systemctl start mysqld

Vous avez maintenant Laravel 5.x avec le support UTF8.

95
scorer

Si vous êtes sur ou mis à jour vers Laravel 5.4 Cela a fonctionné pour moi;

Juste 1 changement. dans AppServiceProvider.php

use Illuminate\Support\Facades\Schema;

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

Comme indiqué dans le guide de migration https://laravel.com/docs/master/migrations#creating-indexes

41
varta

Si quelqu'un d'autre tombe sur cette réponse comme moi, mais pour une raison différente, vous pouvez vérifier votre jeu de caractères/collation Laravel DB.

J'étais en train d'installer une application (Snipe-IT) et j'avais configuré la configuration de la base de données Laravel pour utiliser les éléments suivants:

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

La suppression de mb4 des deux chaînes a résolu le problème, bien que je pense que la réponse d’Antono est la vraie solution au problème.

32
Brendan

Cela a fonctionné pour moi: 

 $table->charset = 'utf8';
 $table->collation = 'utf8_unicode_ci';

18
user3278647

Supprimez mb4 de charset et le classement de config/database.php, puis il s'exécutera avec succès.
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',

13
Ramv V

Pour laravel 5.4, éditez simplement le fichier 

App\Providers\AppServiceProvider.php

use Illuminate\Support\Facades\Schema;

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

Pour laravel 5.6 
Cette solution résout mon problème 
passez à config/database.php 
Trouvez le code ci-dessous

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

Changer ce deux champs 

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

Avec ça 

'charset' => 'utf8',
'collation' => 'utf8_unicode_ci'
10
Avijit Mandal

J'ai rencontré le même problème et je l'ai corrigé en ajoutant les deux lignes ci-dessous dans mon application/database.php

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

Mon fichier ressemble à celui ci-dessous:

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

    ......
10
Muthu17

Dans le fichier config/database.php où:

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

Changez cette ligne en ceci:

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

TO ->
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
5
Faizan Noor

j'ai eu le même problème et j'utilise un wamp 

Solution: Ouvrir le fichier: Config/database.php

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

Merci

4
Purvesh

J'ai ajouté à la migration elle-même

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

oui, je sais que je dois en tenir compte à chaque migration, mais je préférerais que cela soit dissimulé chez un fournisseur de services totalement indépendant

4
Manoj Thapliyal

pour laravel 5.7 écrivez ce code dans appserviceprovider.php

  use Illuminate\Support\Facades\Schema;

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

Si quelqu'un a ce problème même après, les changements mentionnés ci-dessus. Par exemple, dans mon cas, j’ai fait les modifications ci-dessous, 

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

Mais cela ne fonctionnerait pas tout de suite pour deux raisons. La première est que si vous utilisez Lumen au lieu de laravel, vous devrez peut-être d'abord décommenter cette ligne dans votre fichier app.php. 

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

Et vous devez ensuite créer le script de migration à nouveau avec la commande artisan, 

php artisan make:migration <your_table_name>

Depuis lors, seules les modifications que vous avez apportées à ServiceProvider fonctionneront.

2
dilantha111

C'est parce que Laravel 5.4 utilise utf8mb4 qui supporte le stockage des emojis.

Ajoutez ceci dans votre app\Providers\AppServiceProvider.php

use Illuminate\Support\Facades\Schema;

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

et vous devriez être prêt à partir.

2
Irteza Asad

Si vous êtes sur ou mis à jour vers Laravel 5.4 et la dernière version, cela fonctionne;
Seulement 1 changement dans AppServiceProvider.php

use Illuminate\Support\Facades\Schema;

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

Pour Laravel> = 5.6 utilisateurs

Ouvrir le fichier AppServiceProvider.php

Utilisez la classe suivante

use Illuminate\Support\Facades\Schema;

Ensuite, dans la méthode boot, ajoutez la ligne suivante

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

Laravel utilise le jeu de caractères utf8mb4 par défaut, ce 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 puisse créer des index pour ces dernières. Vous pouvez le configurer en appelant la méthode Schema::defaultStringLength dans votre AppServiceProvider:

use Illuminate\Support\Facades\Schema;

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

Vous pouvez vérifier sur

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

1
Barakat Turki

J'ai eu un problème, changez la configuration de 'config/database' 

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

en gardant le même motif dans la base de données.

J'ai ensuite donné le commandement

php artisan migrate
1

Je voudrais souligner que quelque chose qui m'a manqué ...

Je suis nouveau chez Laravel, et je n’ai pas copié le message "use Illuminate ....." car je n’ai vraiment pas fait attention à cela, car juste au-dessus de la fonction boot, vous avez déjà une déclaration use.

Espérons que cela aide quelqu'un

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

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

Changer le jeu de caractères de 'utf8mb4' à 'utf8' et

classement de 'utf8mb4_unicode_ci' à 'utf8_unicode_ci'

dans le fichier config/database.php

Cela a fonctionné pour moi.

1
Chetan Godhani

inclure cette ligne en haut

use Illuminate\Support\Facades\Schema;

puis à l'intérieur de la fonction de démarrage, ajoutez ceci 

public function boot()
{
    Schema::defaultStringLenght(191);
}
0
Danish Jamshed

Le 24 octobre 2016 Taylor Otwell l'auteur de Laravel annoncé sur son Twitter

"utf8mb4" sera le jeu de caractères MySQL par défaut dans Laravel 5.4 pour un meilleur support des emoji. ???? Taylor Otwell Twitter Post

qui avant la version 5.4 le jeu de caractères était utf8

Au cours de ce siècle, de nombreuses applications Web, notamment le chat ou une plate-forme similaire, permettent aux utilisateurs de converser, et beaucoup de gens aiment utiliser emoji ou smiley. et c’est une sorte de super-caractères qui nécessitent plus d’espaces à stocker et qui n’est possible qu’en utilisant utf8mb4 en tant que charset. C'est la raison pour laquelle ils migrent vers utf8mb4 uniquement pour des raisons d'espace.

si vous recherchez dans la classe Illuminate\Database\Schema\Builder, vous verrez que le $defaultStringLength est défini sur 255, et vous pouvez modifier le fait que vous pouvez procéder via la façade Schema et appeler la méthode defaultStringLength et transmettre le nouvelle longueur.

pour effectuer ce changement, appelez cette méthode dans votre classe AppServiceProvider qui se trouve dans le sous-répertoire app\providers comme ceci

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
}

Je suggérerai d'utiliser 191 comme valeur simplement parce que MySQL supporte 767 octets et parce que 767 / 4, qui est le nombre d'octets pris par chaque caractère multi-octets, vous obtiendrez 191.

Pour en savoir plus, cliquez ici Jeu de caractères utf8mb4 (codage Unicode UTF-8 sur 4 octets)Limites du nombre de colonnes et de la taille des lignes de la table

0
Yves Kipondo

Vient d’installer MariaDB 10.2.4 RC, lancez un nouveau projet Laravel 5.4 vierge et une migration par défaut (colonnes varchar (255)).

Pas besoin de changer DB conf et Laravael config/database.php. Ainsi, tout comme @scorer a noté le comportement par défaut de 10.2.2+.

0
kroko

Définir le moteur de base de données 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
Harshad Vala

Donnez une longueur plus courte pour votre chaîne de courrier électronique comme:

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

Et

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

Cela fonctionnera certainement.

0
Abid Shah

Si vous voyez cette erreur, alors vous devez absolument apporter les modifications suivantes au fichier AppServiceProvider.php -> qui se trouve à l'intérieur de app->providers:

changements à faire

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
}

cela devrait résoudre votre problème pour en savoir plus. Vous pouvez voir les nouvelles de Laravel concernant ce problème. https://laravel-news.com/laravel-5-4-key-too-long-error

0
Sandesh Poudel

Spécifiez une longueur inférieure pour votre e-mail:

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

100 TRAVAUX

0
Pir Abdul

Tout était bien décrit dans les autres Anwservous pouvez voir plus de détails dans le lien ci-dessous (recherche avec la clé 'Index Lengths & MySQL/MariaDB ") https://laravel.com/docs/5.5/ migrations

MAIS BIEN Ce n’est pas le propos de cette réponse! la chose est même en faisant ce qui précède vous voudrez obtenir une autre erreur (c'est à ce moment-là que vous aimez lancer la commande php artisan migrate et à cause du problème de la longueur, l'opération est comme coincée au milieu. la solution est en dessous, et la table utilisateur est comme créée sans le reste ou pas complètement correctement) nous devons lancer bac k. la restauration par défaut ne fera pas. parce que l'opération de migration n'a pas aimé finir. 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 que votre bon aller

php artisan migrate:rollback

php artisan migrate
0
Mohamed Allal

Ce problème ne se posera pas si vous utilisez MySQL 5.7.7+ ou MariaDB 10.2.2+.

Pour mettre à jour MariaDB sur votre Mac en utilisant Brew, supprimez tout d'abord le lien entre le fichier actuel: brew unlink mariadb, puis installez un dev en utilisant brew install mariadb --devel

Une fois l’installation terminée, arrêtez/démarrez le service en cours d’exécution: brew services stop mariadb brew services start mariadb

La version actuelle de dev est 10.2.3. Une fois l’installation terminée, vous n’aurez plus à vous en préoccuper et vous pouvez utiliser utf8mb4 (par défaut dans Laravel 5.4) sans revenir à utf8 ni éditer AppServiceProvider comme le propose la documentation de Laravel: https: //laravel.com/docs/master/releases#laravel-5.4 (faites défiler jusqu'à: Migration Longueur de chaîne par défaut)

0
Richard Dawson

SOLUTION:

Commencez par définir defaultStringLength sur 191, dans le app\Providers\AppServiceProvider.php:

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

Modifiez ensuite les valeurs charset et collation comme suit, dans config\database.php:

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

( lien sur le jeu de caractères MariaDB )

0
Naveen Kumar V

Si vous avez essayé toutes les autres réponses et qu'elles n'ont pas fonctionné, vous pouvez supprimer toutes les tables de la base de données puis exécuter la commande migrate en même temps à l'aide de cette commande:

php artisan migrate:fresh
0
Treasure