Pillole Laravel: come evitare di creare implicitamente due colonne chiave sulla stessa tabella

Spread the love

Lo strumento delle migrazioni di Laravel è molto comodo per definire le tabelle di uno schema ma anche per le conseguenti ricadute positive sull’ORM Eloquent ai fini di produrre query con le join già fatte.

Mi riferisco al fatto che è possibile definire i vincoli di chiave esterna (foreign key). Solo che la definizione è un po’ “tricky”. Prendiamo questo esempio: due tabelle customers e orders con una relazione di chiave esterna da customers a orders:

Definizione della tabella customers, un solo attributo chiave, implicitamente definito con increments()
C’è un attributo di riferimento a customer_id

Se faccio girare lo script di migrazione, che si incarica di creare gli oggetti nello schema del DB ottengo un errore:

Illuminate\Database\QueryException  : SQLSTATE[42000]: Syntax error or access violation: 1075 Incorrect table definition; there can be only one auto column and it must be defined as a key

L’errore è abbstanza grave: abbiamo tentato di creare due chiavi: la prima con il campo id la seconda con il campo customer_id. 

All’inizio credevo che fosse un problema della definizione del constraint, e così l’ho scorporato in una seconda invocazione separata: Schema::table eccetera. Invece il problema era com’è stato definito il campo, infatti ho lo stesso errore anche togliendo la definizione del contraint. Il problema è la dimensione del campo:

$table->unsignedInteger('customer_id', 10);

Ora lo spiego qui e sembra ovvio, ma trovarlo, come tutti i buoni martorei, richiede tempo: il metodo $table->unsignedInteger() ha un secondo parametro che non è affatto la dimensione del campo, che lui si regola automaticamente, ma è – disgraziatamente…

 public function unsignedInteger($column, $autoIncrement = false)
    {
        return $this->integer($column, $autoIncrement, true);
    }

… l’informazione $autoIncrement. Essendo disgrazatamente 10 == true in PHP, il campo così viene dichiarato come autoincrement e quindi come chiave primaria generando l’errore. Invece con questa dichiarazione:

La migrazione termina correttamente

In origine, in ogni caso, c’era la mia errata invocazione del metodo.

[Hint: http://bit.ly/2zS9w1v]

Lascia un commento

Your email address will not be published.

Questo sito usa Akismet per ridurre lo spam. Scopri come i tuoi dati vengono elaborati.