migrações laravel do construtor de esquema exclusivas em duas colunas

125

Como posso definir restrições únicas em duas colunas?

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
fonte
1
Infelizmente, esse nível de detalhe está ausente nos documentos do Laravel . Seria tão fácil mencionar isso de passagem. Detalhes como este e - por exemplo - o fato de que a estrutura sempre parece assumir que todas as tabelas terão incremento automático id, dão à estrutura uma sensação de amadorismo nas bordas. Estou reclamando? :-(
cartbeforehorse

Respostas:

277

O segundo parâmetro é definir manualmente o nome do índice exclusivo. Use uma matriz como o primeiro parâmetro para criar uma chave exclusiva em várias colunas.

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

ou (um pouco mais arrumado)

$table->unique(['mytext', 'user_id']);
Collin James
fonte
1
+1 obrigado por isso ... não sei como eu perdi isso na documentação. Eu devo ser cego: P
OACDesigns 29/11
De alguma forma, também perdi o fato de que o segundo parâmetro é nomear manualmente o índice e eu tinha um nome de índice gerado automaticamente, que era muito longo. Obrigado cara! +1
Ciprian Mocanu
1
+1 para array(). Porque eu tentei sem matriz e não funcionou. posso dar o nome da restrição ao executar a chave composta por meio do construtor Schema?
Pankaj
Sim, esse é o segundo parâmetro
Collin James
7
Os nomes de índice gerados estão no formato table_column1_column2...n_uniquese alguém não tiver certeza. Descartar a restrição única seria então fazer referência a isso em #$table->dropUnique('table_column1_column2...n_unique');
Jonathan
19

Simplesmente você pode usar

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

Referência: http://laravel.com/docs/master/migrations#creating-indexes

Como um exemplo:

    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
fonte
4
Porém, isso não garante exclusividade, apenas adiciona um índice composto. Normalmente, você não deseja a mesma tag duas vezes na mesma postagem, portanto, para este caso de uso, é melhor usar ->unique().
okdewit
3
@ FX32 isso faz garantia de singularidade, pois cria uma composição chave primária (que é indexado). No entanto, eu ainda concorda que ->unique()é mais apropriado nesta questão específica, porque 'mytext'provavelmente faria para uma chave ruim como faria com qualquer VARCHARou TEXTcoluna. ->primary([])seria ótimo para garantir exclusividade em números inteiros, como chaves estrangeiras dinâmicas.
Jeff Puckett
2
Observe também que as chaves primárias compostas geralmente são desaprovadas pelos desenvolvedores do Laravel e não são suportadas pelo Eloquent - consulte 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
fonte
uma explicação verbal seria uma adição útil à sua resposta
con