2013-06-04 11 views
25

Ho appena creato un nuovo progetto Laravel 4 e sto scoprendo cose strane che accadono con l'aspetto chiave esterna del generatore di schemi. Se utilizzo il metodo ->foreign() in una delle mie migrazioni, ottengo 150 errori MySQL e errore generale 1005. Secondo la documentazione su laravel.com/docs, i due scenari in basso dovrebbero funzionare? Qualcuno sa perché non lo fanno?Chiavi esterne nel problema delle migrazioni di Laravel 4

Il seguente funziona:

Schema::create('areas', function($table) 
    { 
     $table->engine ='InnoDB'; 
     $table->increments('id'); 

     $table->integer('region_id')->references('id')->on('regions'); 

     $table->string('name', 160); 
     $table->timestamps(); 
    }); 

Ma questi due non funzionano:

Schema::create('areas', function($table) 
    { 
     $table->engine ='InnoDB'; 
     $table->increments('id'); 

     $table->foreign('region_id')->references('id')->on('regions'); 

     $table->string('name', 160); 
     $table->timestamps(); 
    }); 

    Schema::create('areas', function($table) 
    { 
     $table->engine ='InnoDB'; 
     $table->increments('id'); 

     $table->integer('region_id'); 
     $table->foreign('region_id')->references('id')->on('regions'); 

     $table->string('name', 160); 
     $table->timestamps(); 
    }); 
+0

possibile duplicato del [laravel 4 Migrazioni gettare 1072 di errore] (http://stackoverflow.com/questions/16928032/laravel-4-migrations-throwing-1072-error) –

+4

Questa domanda è sul perché il doesn di cui sopra funziona, l'altro riguarda gli errori di MySQL 1072. – JasonMortonNZ

+0

Basta entrare in Laravel e colpire anche questo. La mia soluzione alternativa consisteva nell'aggiungere chiavi esterne utilizzando una migrazione separata. Funziona ma sembra sbagliato. – joemaller

risposta

53

verificare il tipo di id. Laravel 4 crea un ID incrementale con un int (10) non firmato. Se si crea un numero intero di base e si tenta di inserire una chiave esterna, fallirà.

Come suggerito nella documentazione allo this link, è necessario creare l'ID esterno con $table->unsignedInteger(YOUR_ID_NAME); per farlo funzionare.

+5

Ad esempio: (tabella utenti) '$ table-> incrementi ('id');' e (tabella post) '$ table-> unsignedInteger ('user_id');' \ n '$ table-> foreign ('user_id ') -> riferimenti (' id ') -> on (' utenti '); ' – alairock

+0

Stavo usando il tipo corretto così come $ table-> intero (' user_id ') -> unsigned();' E il unsigned la proprietà era stata impostata nel DB ma non ha funzionato per me. Ho aggiornato il mio codice per usare 'unsignedInteger' e tutto ora funziona in modo sorprendente –

+0

Ho avuto lo stesso problema io stesso - Dayle Rees lo ha spiegato bene (con esempi) http://daylerees.com/codebright/eloquent-relationships –

2

funziona, ma a volte devi solo stare attenti e cercare di capire cosa sta succedendo dietro la scena.

Come ho detto nel mio commento. Quando hai eseguito la migrazione per la prima volta senza creare la colonna correlata, i servizi di migrazione di Laravel hanno creato la tua tabella e quindi, quando hai provato a migrare di nuovo, ti darà sempre un errore che dice che la tabella esiste già.

Quindi devi solo drop table areas ed eseguire php artisan migrate di nuovo per risolvere tutto.

EDIT:

Ho appena creato la migrazione (sotto) qui e ha funzionato.

Come potete vedere, non sto usando MySQL, quindi deve essere un problema MySQL. Controlla la documentazione della chiave esterna di MySQL per vedere se i tuoi metadati rientrano nei requisiti InnoDB: http://dev.mysql.com/doc/refman/5.6/en/innodb-foreign-key-constraints.html.

<?php 

use Illuminate\Database\Migrations\Migration; 

class CreateAreasTable extends Migration { 

    /** 
    * Run the migrations. 
    * 
    * @return void 
    */ 
    public function up() 
    { 
     Schema::create('regions', function($table) 
     { 
      // $table->engine = 'InnoDB'; 
      $table->increments('id'); 
      $table->string('name', 160)->unique(); 
      $table->timestamps(); 
     }); 

     Schema::create('areas', function($table) 
     { 
      // $table->engine ='InnoDB'; 
      $table->increments('id'); 

      $table->integer('region_id'); 
      $table->foreign('region_id')->references('id')->on('regions'); 

      $table->string('name', 160); 
      $table->timestamps(); 
     });  
    } 

    /** 
    * Reverse the migrations. 
    * 
    * @return void 
    */ 
    public function down() 
    { 
    Schema::drop('areas'); 
    Schema::drop('regions'); 
    } 

} 

enter image description here

+1

Che non ha funzionato. Ho abbandonato il database, ne ho creato uno nuovo, ho eseguito 'php artisan migration: install' seguito da' php artisan migrate' e gli errori, si verificano ancora, ma solo se includo qualsiasi menzione di '-> foreign()'. – JasonMortonNZ

1

antonio carlos ha ragione, assicurarsi di aver creato prima la tabella di riferimento della propria chiave esterna.

provare a migrare prima le tabelle senza chiavi esterne, quindi effettuare un'altra migrazione assegnando le chiavi esterne. in questo stato, laravel è sicuro che le chiavi di riferimento siano esistenti. e non devi lasciare tavoli durante gli errori artigianali.

7

anche alcune risposte sopra a questa domanda "General error: 1005 Can't create table" Using Laravel Schema Build and Foreign Keys

una sintesi delle risposte elencate lì, compreso il mio:

  1. chiavi esterne in genere richiedono InnoDB, in modo da impostare il motore di default, oppure specificare esplicitamente $table->engine = 'InnoDB'; Se la tabella è già stata creata ed è impostata su MyISAM, potrebbe essere necessario modificarla.

  2. Le chiavi esterne richiedono l'esistenza della tabella di riferimento. Assicurarsi che la tabella di riferimento sia stata creata in una migrazione precedente, prima di creare la chiave. Prendi in considerazione la possibilità di creare le chiavi in ​​una migrazione separata.

  3. Le chiavi esterne richiedono che il tipo di dati sia congruente. Verifica se il campo di riferimento è dello stesso tipo, sia esso firmato o non firmato, indipendentemente dal fatto che la sua lunghezza sia uguale (o inferiore).

  4. Se si passa da una migrazione di codifica manuale all'utilizzo di generatori, accertarsi di verificare il tipo di ID che si sta utilizzando. Artisan utilizza incrementi () per impostazione predefinita, ma Jeffrey Way sembra preferire lo numero intero ('id', vero).

+1

Il mio problema era che si trattava di una tabella creata in precedenza e che era stata impostata per impostazione predefinita su MyISAM. Dopo aver aggiornato la tabella facendo riferimento a InnoDB, tutto ha funzionato alla grande. –

5

Aveva lo stesso problema giorno fa.

Il root del problema è: la colonna con chiave esterna deve essere dello stesso tipo di quella chiave. e si dispone di diverse tipologie: INT/unsigned int

questo rende id un UNSIGNED INT

$table->increments('id'); 

e questo rende region_id un INT

$table->integer('region_id')->references('id')->on('regions'); 

Per risolvere questo problema, fare region_id un UNSIGNED INT

$table->integer('region_id')->unsigned()->references('id')->on('regions'); 
           ^^^^^^^^^ note here 

Documentazione di laravel ha mention su questo:

Nota: Quando si crea una chiave esterna che fa riferimento a un intero incremento, ricordatevi di fare sempre la colonna di chiave esterna non firmato.

Problemi correlati