Schema Builder Laravel migraciones únicas en dos columnas

125

¿Cómo puedo establecer restricciones únicas en dos columnas?

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);
usuario391986
fuente
1
Este nivel de detalle lamentablemente falta en los documentos de Laravel . Sería tan fácil mencionarlo de pasada. Detalles como este y, por ejemplo, el hecho de que el marco siempre parece suponer que cada tabla va a tener un incremento automático id, le da al marco una sensación de aficionado en los bordes. ¿Estoy despotricando? :-(
cartbeforehorse

Respuestas:

277

El segundo parámetro es establecer manualmente el nombre del índice único. Use una matriz como primer parámetro para crear una clave única en varias columnas.

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

o (un poco más ordenado)

$table->unique(['mytext', 'user_id']);
Collin James
fuente
1
+1 gracias por esto ... no estoy seguro de cómo me lo perdí en la documentación. Debo ser ciego: P
OACDesigns
También de alguna manera me perdí el hecho de que el segundo parámetro es nombrar manualmente el índice y tenía un nombre de índice generado automáticamente que era demasiado largo. ¡Gracias hombre! +1
Ciprian Mocanu
1
+1 para array(). Porque lo intenté sin matriz y no funcionó. ¿puedo dar un nombre de restricción mientras ejecuto la clave compuesta a través del generador de esquemas?
Pankaj
Sí, ese es el segundo parámetro
Collin James
77
Los nombres de índice generados están en el formato table_column1_column2...n_uniquesi alguien no está seguro. Dejar caer la restricción única sería hacer referencia a eso en$table->dropUnique('table_column1_column2...n_unique');
Jonathan
19

Simplemente puedes usar

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

Referencia: http://laravel.com/docs/master/migrations#creating-indexes

Como ejemplo:

    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
fuente
44
Sin embargo, esto no garantiza la unicidad, solo agrega un índice compuesto. Por lo general, no desea la misma etiqueta dos veces en la misma publicación, por lo que para este caso de uso es mejor usarla ->unique().
okdewit
3
@ Fx32 esto hace singularidad de garantía, ya que crea un compuesto clave principal (que está indexado). Sin embargo, todavía de acuerdo en que ->unique()es más apropiado en esta cuestión específica, porque 'mytext'probablemente haría una mala clave como lo haría cualquier VARCHARo TEXTcolumna. ->primary([])sería excelente para garantizar la unicidad en los enteros, como las claves externas de pivote.
Jeff Puckett
2
Observe también que las claves primarias compuestas son generalmente mal visto por los desarrolladores laravel, y que no son compatibles con elocuente - ver 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
fuente
una explicación verbal sería una adición útil a su respuesta
con