schema builder laravel migrations uniques sur deux colonnes

125

Comment puis-je définir des contraintes uniques sur deux colonnes?

class MyModel extends Migration {
  public function up()
  {
    Schema::create('storage_trackers', function(Blueprint $table) {
      $table->increments('id');
      $table->string('mytext');
      $table->unsignedInteger('user_id');
      $table->engine = 'InnoDB';
      $table->unique('mytext', 'user_id');
    });
  }
}

MyMode::create(array('mytext' => 'test', 'user_id' => 1);
// this fails??
MyMode::create(array('mytext' => 'test', 'user_id' => 2);
user391986
la source
1
Ce niveau de détail est malheureusement absent des documents Laravel . Ce serait si facile de le mentionner en passant. Des détails comme celui-ci et - par exemple - le fait que le framework semble toujours supposer que chaque table va être auto-incrémentée id, donnent au framework une sensation d'amateur sur les bords. Suis-je déclamé? :-(
cartbeforehorse

Réponses:

277

Le deuxième paramètre consiste à définir manuellement le nom de l'index unique. Utilisez un tableau comme premier paramètre pour créer une clé unique sur plusieurs colonnes.

$table->unique(array('mytext', 'user_id'));

ou (un peu plus soigné)

$table->unique(['mytext', 'user_id']);
Collin James
la source
1
+1 merci pour cela ... je ne sais pas comment je l'ai manqué dans la documentation. Je dois être aveugle: P
OACDesigns
J'ai également raté le fait que le deuxième paramètre consiste à nommer manuellement l'index et j'avais un nom d'index généré automatiquement qui était trop long. Merci mec! +1
Ciprian Mocanu
1
+1 pour array(). Parce que j'ai essayé sans tableau et cela n'a pas fonctionné. puis-je donner le nom de la contrainte lors de l'exécution de la clé composite via le générateur de schéma?
Pankaj
Ouais, c'est le deuxième paramètre
Collin James
7
Les noms d'index générés sont au format table_column1_column2...n_uniquesi quelqu'un n'est pas sûr. L'abandon de la contrainte unique ferait alors référence à cela dans$table->dropUnique('table_column1_column2...n_unique');
Jonathan
19

Vous pouvez simplement utiliser

$table->primary(['first', 'second']);

Référence: http://laravel.com/docs/master/migrations#creating-indexes

Par exemple:

    Schema::create('posts_tags', function (Blueprint $table) {

        $table->integer('post_id')->unsigned();
        $table->integer('tag_id')->unsigned();

        $table->foreign('post_id')->references('id')->on('posts');
        $table->foreign('tag_id')->references('id')->on('tags');

        $table->timestamps();
        $table->softDeletes();

        $table->primary(['post_id', 'tag_id']);
    });
İsmail Atkurt
la source
4
Cela ne garantit pas l'unicité, cela ajoute simplement un index composite. Habituellement, vous ne voulez pas la même balise deux fois sur le même message, donc pour ce cas d'utilisation, il est préférable de l'utiliser ->unique().
okdewit
3
@ Fx32 ce fait unique de garantie , car il crée un composite clé primaire (qui est indexé). Cependant, je suis toujours d'accord que ->unique()c'est plus approprié dans cette question spécifique car cela 'mytext'ferait probablement une mauvaise clé comme le ferait n'importe quelle colonne VARCHARou TEXT. ->primary([])serait idéal pour assurer l'unicité sur les entiers tels que les clés étrangères pivot.
Jeff Puckett
2
Notez également que les clés primaires composites sont généralement mal vues par les développeurs Laravel, et qu'elles ne sont pas prises en charge par Eloquent - voir github.com/laravel/framework/issues/5355
andrechalom
0
DB::statement("ALTER TABLE `project_majr_actvities`
               ADD UNIQUE `unique_index`(`activity_sr_no`, `project_id`)");
Rajendra Rajput
la source
une explication verbale serait un complément utile à votre réponse
con